使用未分配的空间calloc

我只是想知道当我使用非分配空间时编译器不会抛出exception,这里是一个代码例如:

#include  #include  int main() { int i, n; int *a; printf("Number of elements to be entered:"); scanf("%d",&n); a = (int*)calloc(n, sizeof(int)); printf("Enter %d numbers:\n",n); for( i=0 ; i < n ; i++ ) { scanf("%d",&a[i]); } printf("The numbers entered are: "); for( i=0 ; i < n ; i++ ) { printf("%d ",a[i]); } free( a ); return(0); } 

如果n = 3例如我静静地说:

 a[10]=3; 

它会工作,不会抛出exception,我可以打印它,那么使用一个元素出界的影响是什么? 有没有办法知道大小? 因为(sizeof)不会对calloc数组起作用。

你有一些可怕的未定义行为 (UB)。 阅读Lattner的博客,了解每个C程序员应该了解的未定义行为 。

请注意,对于UB,可能会发生非常糟糕的事情,或者说没有什 观察到的行为甚至可能无法从一次运行再到下一次运行(阅读ASLR )。

要解释系统上发生的情况,您需要深入了解实现细节,远低于C或C ++代码。 例如,您可以请求生成的汇编程序(例如,使用gcc -Wall -O -fverbose-asm -S编译代码并查看生成的*.s汇编程序文件)。 或者您可以使用(在Linux上)类似strace(1)的东西来理解所涉及的系统调用 。 我想象在Linux上,对calloc的调用会要求内核至少有一页堆数据(即calloc会使用mmap(2)或sbrk(2) ….)因为页面是4Kbytes数据,您访问的字节实际上是在您的虚拟地址空间中 。

顺便说一下,我邀请您安装并使用一些Linux发行版 。 由于它主要由自由软件组成 ,因此您可以研究所涉及的源代码(包括您的代码,标准C库和Linux内核,甚至是编译器)。 这可能需要你很多年,但你原则上可以理解所有的实现细节。

阅读乔尔的泄漏抽象定律 ……

有没有办法知道尺寸? (一些堆分配的数据)

不,不是在便携式C中。您应该自己管理尺寸(即有一些方法来了解它)。 一个有用的技巧可能是将其保持在数组数据附近,例如在包含大小的struct中,并以灵活的数组成员结束。 但你仍然需要一些约定来获得大小。

超出界限访问数据会给您带来未定义的行为,这意味着任何事情都可能发生。

如果远离界限,由于访问未映射或受保护的内存页面,可能会出现分段错误。 但是,这假设您的代码到机器代码的映射有点简单。

事实是,编译器只会让您觉得您的代码直接映射到机器代码。 当你通过引起未定义的行为来破坏规则的那一刻,幻觉可能以一些非常奇怪的方式破坏,这就是未定义的行为。

对不起,您无法知道已分配数组的大小(请参阅: 确定c中动态分配内存的大小 )

访问一个越界数组是否会抛出“exception”取决于数组/ MMU边界的位置。 无论如何,它不是可靠的!

要获得“真实”exception,请切换到C ++,删除calloc ,使用vector::at