【问题标题】:Writing to pointer out of bounds after malloc() not causing error在 malloc() 之后写入指针越界不会导致错误
【发布时间】:2011-05-30 21:43:06
【问题描述】:

当我尝试下面的代码时,它工作正常。我错过了什么吗?

main()
{
    int *p;
    p=malloc(sizeof(int));
    printf("size of p=%d\n",sizeof(p));
    p[500]=999999;
    printf("p[0]=%d",p[500]);
    return 0;
}

我尝试使用 malloc(0*sizeof(int)) 或其他任何方法,但效果很好。只有当我根本不使用 malloc 时,程序才会崩溃。因此,即使我为数组 p 分配 0 内存,它仍然可以正确存储值。那么为什么我还要打扰 malloc 呢?

【问题讨论】:

  • 尝试用一个非常大的数字替换 500 .....
  • 是的,它会因大量数字而崩溃。感谢所有回答的人。

标签: c malloc memory-corruption


【解决方案1】:

它可能看起来工作正常,但它根本不是很安全。通过在分配的内存块之外写入数据,您正在覆盖一些您不应该覆盖的数据。这是导致段错误和其他内存错误的最大原因之一,而您所观察到的它在这个短程序中似乎有效,这使得追查根本原因变得如此困难。

阅读this article,尤其是关于内存损坏的部分,以开始了解问题。

Valgrind 是一款出色的工具,可用于分析您提供的内存错误。

@David 发表了很好的评论。比较运行your code 和运行the following code 的结果。请注意,后者会在 ideone.com(单击链接)上导致运行时错误(几乎没有有用的输出!),而前者会如您所见。

int main(void)
{
    int *p;
    p=malloc(sizeof(int));
    printf("size of p=%d\n",sizeof(p));
    p[500]=999999;
    printf("p[0]=%d",p[500]);
    p[500000]=42;
    printf("p[0]=%d",p[500000]);
    return 0;
}

【讨论】:

    【解决方案2】:

    如果你不分配内存,p 里面就有垃圾,所以写入它很可能会失败。一旦您进行了有效的 malloc 调用,p 将指向有效的内存位置,您可以对其进行写入。您正在覆盖您不应该写入的内存,但没有人会握住您的手并告诉您这件事。如果你运行你的程序和一个内存调试器,比如 valgrind,它会告诉你。 欢迎来到 C.

    【讨论】:

      【解决方案3】:

      写到你记忆的尽头是 Undefined Behaviour™,这意味着任何事情都可能发生 - 包括你的程序运行,就好像你刚刚做的事情是完全合法的一样。您的程序运行与 malloc(501*sizeof(int)) 一样的原因完全是特定于实现的,并且确实可以特定于任何事物,包括月相。

      【讨论】:

        【解决方案4】:

        这是因为无论您使用 malloc() 使用什么大小,都会为 P 分配一些地址。虽然,如果使用零大小,您将引用无效内存,因为内存尚未分配,但它可能位于不会导致程序崩溃的位置,尽管行为将是未定义的。

        现在如果你不使用 malloc(),它将指向一个垃圾位置并试图访问可能导致程序崩溃的位置。

        【讨论】:

          【解决方案5】:

          我用 malloc(0*sizeof(int)) 试过了

          根据 C99,如果传递给 malloc 的大小为 0,则 C 运行时可以返回 NULL 指针,或者分配的行为就像请求用于非零分配一样,除了返回的指针不应该被取消引用.所以它是实现定义的(例如,一些实现返回一个零长度的缓冲区),在你的情况下你没有得到一个 NULL 指针,但是你正在使用一个你不应该使用的指针。如果你在不同的运行时尝试它,你可以返回一个 NULL 指针。

          【讨论】:

            【解决方案6】:

            当您调用 malloc() 时,会为您从一个较大的页面中切出一小块内存。

                malloc(sizeof(int));
            

            实际上并不在 32 位机器上分配 4 个字节(分配器将其填充到最小大小)+ 用于在其生命周期内跟踪块的堆元数据大小(块根据其大小放置在 bin 中并标记分配器正在使用或免费)。 hxxp://en.wikipedia.org/wiki/Malloc 或更具体地说是 hxxp://en.wikipedia.org/wiki/Malloc#dlmalloc_and_its_derivatives 如果您在 Linux 上进行测试。

            因此,超出块的范围写入并不一定意味着您会崩溃。在 p+5000 处,您不会在为该初始块分配的页面范围之外进行写入,因此您在技术上正在写入有效的映射地址。欢迎来到内存损坏。 http://www.google.com/search?sourceid=chrome&ie=UTF-8&q=heap+overflows

            【讨论】:

              【解决方案7】:

              我们的CheckPointer 工具可以检测到此错误。它知道 p 的分配是 4 字节的块,因此分配是在分配 p 的区域之外的。它会告诉你 p[500] 的赋值是错误的。

              【讨论】:

                猜你喜欢
                • 2020-05-12
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2021-08-14
                相关资源
                最近更新 更多