0

我正在使用 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]
有人可以解释为什么不会导致访问冲突吗?

4

5 回答 5

4

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

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

您正在缩小尺寸:

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

在此最大索引值之后可以1pTest[1].

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

于 2013-08-01T09:05:04.820 回答
3

你在那里做的是未定义的行为。它“可能”acvio,它可能会出现段错误。另一方面,它可能会向您的猫发送电子邮件。你不能依赖未定义的行为,因为它是未定义的。

于 2013-08-01T09:04:56.657 回答
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
于 2013-08-01T09:08:13.503 回答
0

在分配的内存之外访问是未定义的。在您遇到某种段边界之前,您通常不会遇到访问冲突。否则,如前所述,行为未定义。

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

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

于 2013-08-01T09:11:09.007 回答
0

这完全取决于内存分配器从哪里获取内存以及大小。

通常,内存取自“正常”堆空间的末尾,并根据需要进行扩展。释放后,为了不立即释放所有我们可以释放的东西,有一定的滞后性,以尽量减少对操作系统的调用次数。

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

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

于 2013-08-01T09:29:40.723 回答