【发布时间】:2020-11-27 21:33:25
【问题描述】:
在以下代码上运行时,Facebook 的 Infer 工具会给出以下输出:
Analysis finished in 397mss
Found 1 issue
test.c:18: error: RESOURCE_LEAK
resource of type `_IO_FILE` acquired by call to `fopen()` at line 13, column 13 is not released after line 18, column 2.
16. return 1;
17. }
18. > fp = check_file_size_and_reopen(fp);
19.
20. fclose(fp);
Summary of the reports
RESOURCE_LEAK: 1
代码如下:
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#define FILE_MAX_SIZE 256000
#define FILE_NAME "dump.log"
#define LAST_FILE_NAME "dump.log2"
FILE* check_file_size_and_reopen(FILE* fp);
int main(void) {
FILE *fp = fopen(FILE_NAME, "a+");
if (!fp) {
return 1;
}
fp = check_file_size_and_reopen(fp);
fclose(fp);
return 0;
}
FILE* check_file_size_and_reopen(FILE* fp) {
struct stat info;
fstat(fileno(fp), &info);
if (info.st_size > FILE_MAX_SIZE) {
fclose(fp);
rename(FILE_NAME, LAST_FILE_NAME);
fp = fopen(FILE_NAME,"a+");
}
return fp;
}
如果文件指针作为FILE** fp 传入并被修改,则会给出相同的警告,但如果对check_file_size_and_reopen() 的调用被替换为相同的内联代码,则不会。
这是因为 Infer 无法确定 fp 在传递给另一个函数时调用 fclose() 之前没有被修改,还是这里实际上存在潜在的资源泄漏?
更新
有趣的是,似乎是对fstat() 的调用让我们感到不安。以下没有警告:
FILE* check_file_size_and_reopen(FILE* fp) {
struct stat info;
int fd = fileno(fp);
(void)fd;
info.st_size = 0;
if (info.st_size <= FILE_MAX_SIZE) {
return fp;
}
fclose(fp);
rename(FILE_NAME, LAST_FILE_NAME);
return fopen(FILE_NAME,"a+");
}
但是,这与以前的警告相同:
FILE* check_file_size_and_reopen(FILE* fp) {
struct stat info;
int fd = fileno(fp);
fstat(fd, &info);
if (info.st_size <= FILE_MAX_SIZE) {
return fp;
}
fclose(fp);
rename(FILE_NAME, LAST_FILE_NAME);
return fopen(FILE_NAME,"a+");
}
【问题讨论】:
-
对我来说似乎是误报
-
实际错误不是资源泄漏而是相反,如果第二个
fopen失败,则将无效指针传递给fclose。
标签: c memory-leaks resource-leak