我最近正在尝试在现有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]
时就回忆起来
我在这里缺少什么写东西,以至于不能避免空终止的风险?
答案 0 :(得分:0)
我在这里缺少什么写东西,以至于不能避免空终止的风险?
您对fread
的工作方式的理解不正确。
fread()
不会使输入缓冲区终止。不仅如此,如果从中读取的文件包含二进制数据,则缓冲区可以包含任意数量的(可以为零,可以为非零)空字符。
如果您确定文件仅包含文本内容,则可以执行以下操作:
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;
}