【问题标题】:Why does this code crash during a dynamic allocation?为什么此代码在动态分配期间会崩溃?
【发布时间】:2009-06-05 09:13:15
【问题描述】:

我在下面有这段代码 sn-p,它在“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。这实际上适用于我的英特尔电脑,但不适用于 arm 机器。

【问题讨论】:

  • 分配前file_size给你什么?
  • 它是一个非零、非负值。
  • 这也可能对您有所帮助:xkcd.com/292
  • 你可以在 malloc 赋值时将强制转换为 (char *),它在 c 上是自动的(但不是在所有 c++ 编译器中)

标签: c malloc


【解决方案1】:

您可以在手册中看到这一点 - ftell() 在错误时返回 -1,而不是零。

【讨论】:

  • 如果这是问题所在(我怀疑是),那么我认为他有一个非标准的 malloc。 malloc(0) 不应该崩溃。
  • 我同意,但我们只有他的话,那就是它崩溃的地方。
  • 它在 str 分配上崩溃,至少堆栈跟踪是这样说的。我尝试打印 file_size 值.. 得到 140 值。
【解决方案2】:

在使用变量之前,将它们打印出来,尤其是file_size。你可能会得到一个惊喜。

【讨论】:

    【解决方案3】:

    ftell(fptr) 返回的值是多少? 也许它太大了? 如果它返回long int indeed,那么它可能会溢出你的int,你会在那里得到一个负值。

    【讨论】:

      【解决方案4】:

      malloc 需要一个 size_t 作为参数。 size_t 是 unsigned int 或 unsigned long 的 typedef(取决于平台),这里的键是 UNSIGNED。

      您使用 int 表示 file_size,而 int 可能只有 16 位(您使用的是 ARM,所以我认为这是一个 MCU)。一个有符号的 16 位只能支持 32,768 字节的文件大小(以字节为单位),因此,如果您有一个大文件(实际上并没有那么大,只是 >32K),file_size 会溢出。

      我认为编译器告诉了你,但你选择忽略它......现在 mallow 接受一个无符号参数,所以它会自动转换你对 filesize+1 的签名评估(即使它被深度溢出,一个有符号的大时间负) 并尝试分配内存。 这可能意味着您尝试分配的内存比此嵌入式应用程序多得多。不能(不应该崩溃)。

      我真的看不出崩溃的原因(除了坏库,在嵌入式 C 中很常见,因为用户基数反馈低),但我看到了导致不良行为的错误。

      我什至不会去问“为什么要使用 goto 东西”,因为答案会引发很多火焰。

      【讨论】:

        【解决方案5】:

        在不正确的地址上执行缓冲区溢出或 free() 之前的某个地方!!!-)

        【讨论】:

          【解决方案6】:

          在一般意义上...我根本不想 bash,但是您的代码有点糟糕。使用编码标准通常会让事情变得更清楚......也就是说,尼尔可能得到了答案。

          【讨论】:

          • 是的,我同意。这实际上是我正在尝试使用的一个开源库。 =)
          【解决方案7】:

          这不太可能是你的问题,但你记得吗

          #include <stdlib.h>
          

          所以 malloc 的原型在范围内?在这种情况下,编译器不会警告你,因为它的返回值是免费的。在 C 中,没有理由强制转换 malloc 的返回值。所以:

          str =  malloc(file_size + 1);
          

          顺便说一句,空白是免费的。

          最后,如果您希望能够在多个平台上以这种方式推断文件的大小,您应该以二进制模式打开文件。

          基于:

          str[file_size] = '\0';
          

          您似乎隐含地假设该文件不能包含嵌入的 \0 字符。如果你确实做到了,我觉得这是一个危险的假设。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-01-14
            • 1970-01-01
            • 2014-08-12
            • 2021-08-06
            • 2018-10-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多