我最近正在尝试在现有的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]
型时,memmove
会我在这里缺少什么来让它写入,从而无法避免空终止风险?
假设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] = ' ';
}
else
{
abort(); // fread return value is unexpected
}
assert(strlen(buff) <= readbytes);
我在这里缺少什么来让它写入,以便避免空终止风险?
您对fread
如何工作的理解是不正确的。
fread()
不 null 终止输入缓冲区。不仅如此,如果从中读取的文件包含二进制数据,则缓冲区可能包含任意数量的(可以是零,可以是非零)空字符。
如果确定文件仅包含文本内容,则可以执行以下操作:
- 确保读取的字符数比缓冲区可以容纳的字符数少一个。
- 使用空字符终止缓冲区。
- 此外,您需要交换两个中间参数。请参阅
fread
文档,了解中间两个参数的含义。
size_t readbytes = fread(buff, 1, length - 1, file);
buff[readbytes] = ' ';
从 https://en.cppreference.com/w/c/io/fread:
buffer- 指向存储
读取对象的数组的指针大小- 每个对象的大小(以字节
为单位)计数- 要读取的对象的数量流- 要读取
的流
假设输入文件有一行,内容为:
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);
适合您的用例。
您可以使用字符串和文件流来完全避免此问题。当您使用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;
}