为什么mac OS X不会在此代码中引发运行时错误?

时间:2013-08-01 09:03:04

标签: c memory-management

我正在使用OS X.我已编写了一个简单的代码,如

pTest       =   (char*)malloc(sizeof(char) * 3);

pTest[0]    =   0;
pTest[1]    =   1;
pTest[2]    =   2;

pTest       =   (char*)realloc(pTest, sizeof(char) * 2);

printf("%d %d %d %d\n", pTest[0], pTest[1], pTest[2], pTest[3]);
pTest[3]    =   100; // memory access violation.

如果此代码不会导致访问冲突,为什么realloc需要?尽管我们在堆段中分配了一小块内存,但我们所要做的就是访问另一个索引,例如pTest[100]pTest[2048]pTest[65536]。 有人可以解释为什么不会导致访问冲突?

5 个答案:

答案 0 :(得分:4)

  

void *realloc(void *ptr, size_t size);

     

realloc()函数将ptr指向的内存块的大小更改为size bytes。内容将在从区域开始到最小的范围内保持不变旧的和新的尺寸。

你缩小了尺寸:

pTest   =   (char*)realloc(pTest, sizeof(char) * 2);
                                      ^
                                      | 
                                     changed size of array to two chars only

此最大索引值可以1pTest[1]

任何索引值> 1,导致内存冲突 - 非法内存访问 - 运行时未定义的行为。

答案 1 :(得分:3)

你在做什么是未定义的行为。它'可能'是accvio,它可能是段错误。另一方面,它可能会发送电子邮件给你的猫。您不能依赖未定义的行为,因为它未定义。

答案 2 :(得分:0)

首先,您使用mealloc在堆中有一个内存存储0,1,2

然后你使用realloc(pTest sizeof(char )*2);它削减了内存,现在只有0,1

当您打印pTest[3],时,您已经从已释放的内存中读取数据。可能内存仍然没有使用,只是保留旧值,但这不安全。

然后你给pTest[3]一个值。但是你意识到你只有一个阵列大小2 吗?你只能使用pTese[0] and pTest[1]!

我修复了你的代码:

pTest       =   (char*)malloc(sizeof(char) * 3);

pTest[0]    =   0;
pTest[1]    =   1;
pTest[2]    =   2;

pTest       =   (char*)realloc(pTest, sizeof(char) * 4);// at lest 4 

printf("%d %d %d \n", pTest[0], pTest[1], pTest[2]);//  pTest[3]) is still unkonw;
pTest[3]    =   100; //it is ok now

答案 3 :(得分:0)

未定义访问已分配内存之外的内容。在达到某种分段边界之前,通常不会获得访问冲突。否则,如上所述,行为未定义。

使用数组时,请保持在索引边界内。如果您需要数组索引值的访问冲突警告,则必须自己添加它们。

此外,你的realloc只是给内存管理器一个线索,你不需要你最初分配的最后一个字节。存储器管理器可以返回相同的指针值或一些其他新的指针值。您唯一关心的是您不要超过内存分配。如果这样做,那么将导致未定义的行为,有时候在应用程序的后期很晚。

答案 4 :(得分:0)

它完全取决于内存分配器占用内存的位置和大小。

通常,内存取自“普通”堆空间的末尾,根据需要进行扩展。在释放之后,存在一定的滞后现象,以便不立即释放所有可能的内容,以便最小化对OS的调用次数。

此外,如果内存在堆末尾,则释放的内存将仅添加到malloc()可用的内存区域。它可能会更改其内容以便成为管理可用内存的链接列表的一部分,但读取访问将成功,因为它是分配给该进程的内存的一部分。

Onliy如果我在堆的末尾有相当大的部分,其free()导致堆实际收缩,或者内存块太大以至于它是通过mmap()分配的, free()之后访问它实际上会导致访问冲突。