不正确的NULL终止c / c ++

时间:2019-04-05 05:56:19

标签: c++

我最近正在尝试在现有c ++源(与C混合)上使用静态代码分析器。我尝试这样的操作

时发现很多错误发生
char* buff= new char[length];
size_t readbytes = fread(buff,length,1, file)

我在buff上得到了不正确的空指针终止。我尝试过这样的事情-

if((readbytes=fread(buff,length,1,file))<length){ /*dont do anything*/}
else {/*rest of the code*/}

不起作用。 还尝试用strlen(buff) == length进行检查-也不起作用。

我的memcpy遇到类似的高风险问题,当我的目标类型为char[constant size]时就回忆起来

我在这里缺少什么写东西,以至于不能避免空终止的风险?

3 个答案:

答案 0 :(得分:0)

  

我在这里缺少什么写东西,以至于不能避免空终止的风险?

您对fread的工作方式的理解不正确。

fread()不会使输入缓冲区终止。不仅如此,如果从中读取的文件包含二进制数据,则缓冲区可以包含任意数量的(可以为零,可以为非零)空字符。

如果您确定文件仅包含文本内容,则可以执行以下操作:

  1. 确保读取的字符数少于缓冲区可容纳的字符数。
  2. 使用空字符终止缓冲区。
  3. 此外,您需要交换两个中间参数。有关两个中间参数的含义,请参见fread documentation

size_t readbytes = fread(buff, 1, length - 1, file);
buff[readbytes] = '\0';

来自https://en.cppreference.com/w/c/io/fread

  

缓冲区-指向存储读取对象的数组的指针
   size -每个对象的大小(以字节为单位)
   count -要读取的对象数
  信息流-要阅读的信息流

假设输入文件只有一行,内容为:

abcdef

缓冲区定义为:

char buff[20];

如果您使用

size_t n = fread(buff, 20, 1, file);

然后,n将为0。您请求读取1个大小为20的对象,并且文件中只有7个字符(我也包括换行符)。

如果您使用

size_t n = fread(buff, 1, 20, file);

然后,n将为7。您请求读取20个大小为1的对象,但是该功能只能读取7个大小为1的对象。

现在,您可以决定是否

size_t readbytes = fread(buff, length - 1, 1, file);

size_t readbytes = fread(buff, 1, length - 1, file);

适合您的用例。

答案 1 :(得分:0)

假设fread首先要添加一个终止null是错误的。或在缓冲区中间不存在终止null。您应该分配+1字节并手动添加终止null,以确保它存在于缓冲区中的某个位置:

char * buff{new ichar[length + 1]};
size_t readbytes{fread(buff, length, 1, file)};
if(readbytes <= length)
{
    buff = readbytes[readbytes] = '\0';
}
else
{
    abort(); // fread return value is unexpected
}
assert(strlen(buff) <= readbytes);

答案 2 :(得分:-1)

您可以使用字符串和文件流完全避免此问题。使用C ++时,最好也使用它提供的所有那些不错的流函数来避免此类问题。

#include <iostream>
#include <fstream>

const char* filePath = "yourFile.txt";

int main() {
    std::string line = "";
    std::ifstream inFile (filePath, std::ifstream::in);
    if (inFile.good()) {
        std::getline(inFile, line, '\n');
    }
    inFile.close();
    // more checks here (inFile.fail() || inFile.bad()) + cleanup
    /* Do what you want with line */
    return 0;
}