下面有我的代码片段,它在动作分配'str'中的分配过程中崩溃。
char *str;
int file_size;
FILE *fptr;
if (!(fptr = fopen(filename, "r"))) goto error1;
if ((fseek(fptr, 0L, SEEK_END) != 0)) goto error2;
if (!(file_size=ftell(fptr))) goto error2;
if ((fseek(fptr, 0L, SEEK_SET) != 0)) goto error2;
str = (char*)malloc(file_size+1);
if (fread(str, file_size, 1, fptr) != 1) {
free(str);
goto error2;
}
str[file_size] = '\0';
fclose(fptr);
file_size为非零,非负小于140的值
我正在使用ARM。这实际上适用于我的intel pc,但不适用于arm机器。
答案 0 :(得分:7)
你可以在手册中看到这一点 - ftell()在出错时返回-1,而不是零。
答案 1 :(得分:3)
在使用之前打印变量,尤其是file_size
。你可能会感到意外。
答案 2 :(得分:2)
ftell(fptr)
返回的值是多少?
也许它太大了?
如果它返回long int indeed,那么它可能会溢出你的int并且你会得到一个负值。
答案 3 :(得分:2)
malloc期望size_t用于参数。 size_t是unsigned int或unsigned long的typedef(取决于平台),这里的关键是UNSIGNED。
你正在为file_size使用int,而int可能只有16位(你正在使用ARM,所以我认为这是一个MCU)。有符号的16位只能支持32,768字节的文件大小(以字节为单位),因此,如果你有一个大文件(实际上不是那么大,只有> 32K),file_size会溢出。
我认为编译器告诉过你,但是你选择忽略它...现在锦葵采用无符号参数,所以它会自动转换你对signedize + 1的签名评估(即使它已经深度溢出,一个签名的大时间负面并尝试分配内存。 这可能意味着您尝试分配的内存远远超过此嵌入式应用程序。不能(不应该崩溃)。
我真的没有看到崩溃的原因(除了一个坏的库,由于用户群反馈较少,嵌入式C中很常见,但是我看到错误会导致不必要的行为。
我甚至不去问“为什么会有这些东西”,因为答案会引发很多火焰评论。
答案 4 :(得分:1)
在你做缓冲区溢出之前的某个地方或在不正确的地址上的free()!!! - )
答案 5 :(得分:0)
从一般意义上说......我根本不是要打击,但你的代码有点糟糕。使用编码标准通常会让事情变得更清楚......那就是说,Neil可能得到了答案。
答案 6 :(得分:0)
这不太可能是你的问题,但你记得
#include <stdlib.h>
以便malloc的原型在范围内?在这种情况下编译器不会警告您,因为它的返回值无偿转换。在C中,没有理由强制转换malloc的返回值。所以:
str = malloc(file_size + 1);
顺便说一下,空白是免费的。
最后,如果您希望能够在多个平台上以这种方式推断其大小,则应以二进制模式打开文件。
基于:
str[file_size] = '\0';
您似乎隐含地假设该文件不能包含嵌入的\ 0字符。如果你确实在做这件事,这对我来说是一个危险的假设。