【问题标题】:Behavior of malloc : is first 'out of bounds' value always NULL / 0? [duplicate]malloc 的行为:第一个“越界”值是否始终为 NULL / 0? [复制]
【发布时间】:2017-01-24 21:50:13
【问题描述】:

我最近对 ​​C 中 malloc 函数的行为很感兴趣,并且我观察到了一个有趣的行为。看起来 malloc 为 NULL 后的第一个“越界”值(或至少返回被if 视为错误的东西)。 这是一个插图:

int main (){

    int i;
    double * d_ptr = malloc (10 * sizeof (double)); //malloc 10 double
    for (i=0 ; i<10 ; i++){                         // initialise them ...
        d_ptr[i] = 42;
    }

    for (i=0 ;i <50 ; i++){ /// loop obviously trying to go out of bounds
        if (d_ptr[i]){
            printf("i=%d,d[%d]=%f\n",i,i,d_ptr[i]);
        }
        else {
            printf("out of bounds : i=%d\n",i);
            break;
        }
    }

    printf("exited 'out of bounds loop' safely\n");
    free(d_ptr);
    return 0;
}

这是输出:

i=0,d[0]=42.000000
i=1,d[1]=42.000000
i=2,d[2]=42.000000
i=3,d[3]=42.000000
i=4,d[4]=42.000000
i=5,d[5]=42.000000
i=6,d[6]=42.000000
i=7,d[7]=42.000000
i=8,d[8]=42.000000
i=9,d[9]=42.000000
out of bounds : i=10
exited 'out of bounds loop' safely

我的问题是:

  • 这种行为是否可以预测?我尝试了一堆变量类型,malloc 的不同大小,我总是安全地退出循环。

  • 如果它是可预测的,它是否可以成为循环指针的可靠方法,在这种情况下知道它们的“大小”会很棘手,或者需要大量重写?

  • 最后,更深层的解释是什么?做 malloc 在要求的内存空间后多分配一个字 分配?

【问题讨论】:

  • 越界访问是未定义的行为。任何事情都有可能发生,这绝对是不可预测的。
  • 在分配内存后尝试释放内存,然后分配一个稍小的块,看看在新块的末尾是否仍然得到0

标签: c pointers segmentation-fault malloc


【解决方案1】:

当您调用未定义的行为时,任何事情都可能发生。你的程序可能会崩溃,它可能会显示奇怪的结果,或者它可能看起来工作正常。在这种情况下,你得到了后者。

在valgrind下运行这个程序,结果如下:

==22701== Memcheck, a memory error detector
==22701== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==22701== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==22701== Command: /tmp/x1
==22701==
i=0,d[0]=42.000000
i=1,d[1]=42.000000
i=2,d[2]=42.000000
i=3,d[3]=42.000000
i=4,d[4]=42.000000
i=5,d[5]=42.000000
i=6,d[6]=42.000000
i=7,d[7]=42.000000
i=8,d[8]=42.000000
i=9,d[9]=42.000000
==22701== Invalid read of size 8
==22701==    at 0x4005C4: main (x1.c:13)
==22701==  Address 0x4c18090 is 0 bytes after a block of size 80 alloc'd
==22701==    at 0x4A0610C: malloc (vg_replace_malloc.c:195)
==22701==    by 0x400579: main (x1.c:7)
==22701==
out of bounds : i=10
exited 'out of bounds loop' safely
==22701==
==22701== HEAP SUMMARY:
==22701==     in use at exit: 0 bytes in 0 blocks
==22701==   total heap usage: 1 allocs, 1 frees, 80 bytes allocated
==22701==
==22701== All heap blocks were freed -- no leaks are possible
==22701==
==22701== For counts of detected and suppressed errors, rerun with: -v
==22701== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)

如您所见,这被正确识别为读取超出了 malloc'ed 缓冲区的末尾。

程序会崩溃并不意味着它会崩溃。

所以,这种行为是不可预测的。

【讨论】:

    【解决方案2】:

    “这种行为可以预测吗?”不,是undefined。 “最后,更深层次的解释是什么? malloc 在它被要求分配的内存空间之后是否额外分配了一个字?”不,至少在我所知道的任何实现中,您都不应该故意尝试越界访问数组或取消引用未初始化的数据,因为它总是会导致未定义的行为。在某些情况下,您可能会幸运地使用 UB,即使在调用它之后程序也会按预期运行,请注意 time travelling nasal dragons

    【讨论】:

    • 感谢您的建议和时间旅行的鼻龙!有时候,没有什么比一张漂亮的图片更能记住一个冷酷的事实了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-25
    • 1970-01-01
    • 2012-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多