malloc的行为:首先是'越界'值总是NULL / 0?

时间:2017-01-24 21:50:14

标签: c pointers segmentation-fault malloc

我最近对C中malloc函数的行为感兴趣,并且我观察到了一个有趣的行为。它看起来像是malloc结果为NULL后的第一个'越界'值(或者至少返回if认为为false的东西)。 这是一个例子:

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 在被要求的内存空间之后分配一个额外的单词 分配?

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:2)

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

在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缓冲区的末尾读取。

仅仅因为程序崩溃并不意味着它会发生。

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