为什么在动态分配期间此代码会崩溃?

时间:2009-06-05 09:13:16

标签: c malloc

下面有我的代码片段,它在动作分配'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机器。

7 个答案:

答案 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字符。如果你确实在做这件事,这对我来说是一个危险的假设。