我最近对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的不同大小,我总是安全退出循环。
如果它是可预测的,是否可以成为循环指针的可靠方式,因为知道它们的“大小”会很棘手,或者需要大量重写?
答案 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缓冲区的末尾读取。
仅仅因为程序崩溃并不意味着它会发生。
所以没有,这种行为是不可预测的。