C++ istream :: read导致未定义的行为

xte*_*408 1 c++ binaryfiles binary-data

我使用以下代码将n字符从二进制文件复制到char*变量:

 std::ifstream is ("write.abc", std::ifstream::binary);
  if (is) {
    // get length of file:
    is.seekg (0, is.end);
    int length = is.tellg();
    is.seekg (0, is.beg);

    char * buffer = new char [length];

    std::cout << "Reading " << length << " characters... ";
    // read data as a block:
    is.read (buffer,length);
    std::cout << "length of buffer: "<<strlen(buffer) <<endl;
    std::cout << "Content of buffer: "<<buffer <<endl;
.......
Run Code Online (Sandbox Code Playgroud)

我的文件内容:

在此输入图像描述

这是编译的结果: 在此输入图像描述

我的问题如下:我等着:

缓冲长度:13

缓冲内容:abcdefghjklmn

有人可以帮我解释一下结果吗?

Pau*_*l R 8

您的缓冲区未终止 - 您需要分配一个额外的char并将其设置为'\0',否则它只是一个未终止的C字符串,因此strlen很可能返回一个无效值,并且尝试打印该字符串通常会产生垃圾.

char * buffer = new char [length + 1]; // <<< allocate space for `length`
                                       //     characters + terminator

std::cout << "Reading " << length << " characters... ";
// read data as a block:
is.read (buffer,length);
buffer[length] = '\0'; // <<< terminate C-style string
Run Code Online (Sandbox Code Playgroud)

请注意,使用适当的C++样式std::string而不是旧式的C样式char *字符串可以避免这种和其他常见问题,并且通常更简单,更稳健.如果您正在阅读二进制数据而不是文本,请考虑使用std::vector<unsigned char>.

  • 同意.您可以打印var'length'并将其与strlen(buffer)的输出进行比较.他们可能不会匹配.strlen搜索第一个NULL字节\ 0.它只是在30个字节后找到一个 (2认同)