缩小char时,realloc()的行为不符合预期*

时间:2015-08-30 01:10:35

标签: c memory memory-management

我试图用realloc()缩小指针“ptr”,如下面的示例代码所示:

char * ptr = malloc(sizeof(char) * 7);
int i;
for(i = 0;i<7;i++){
    ptr[i]= "pointer"[i];
}
puts(ptr);
ptr = realloc(ptr,sizeof(char) * 3);
puts(ptr);
free(ptr);

期望代码释放未使用的内存我认为它会返回以下内容:

pointer
poi

但是,它会返回:

pointer
pointer

这是编译器的错误,还是我对realloc()的理解错误?

3 个答案:

答案 0 :(得分:6)

你误解了realloc。 realloc不一定会将数据移动到新位置,并且由于您缩小了内存,因此几乎可以肯定(取决于实现)。它不(必然)修改原始内容,在您的情况下它没有。您的程序正在调用未定义的行为,除程序外没有错误。 (使用不指向空终止字符串的char *调用puts是错误。)

答案 1 :(得分:1)

这是因为缩小时指针没有被改变,将数据留在同一个地方。

所以剩余的5个字节nter\0仍在那里,在分配的区域之外,但在它旁边的同一个地方。注意C中的字符串是以空值终止的,这意味着符号\0(值为零的字符)用作标记来确定字符串的结束位置。

当您打印C字符串时,它将一直打印,直到找到\0,即使此\0超出了已分配的内存空间的范围,也可以调用通用的字符串&#34;未定义的行为&#34;,你不应该做的事情,可能会或可能不会,或者可能会或可能不会崩溃,具体取决于条件。

即使它确实将您的变量移动到内存中的其他位置,它也只会移动poi部分,并且会丢失null终止符,导致您的字符串格式错误,导致更多未定义行为。它会打印内存垃圾,直到它崩溃或找到\0

答案 2 :(得分:0)

realloc返回一个更新的指针,该指针指向(至少)所请求大小的一块内存。它可以通过分配新的内存块并通过返回原始指针值来释放旧的内存(并更新系统的内部簿记信息以跟踪更新的大小)来实现。 。如果它分配了一大块新内存,它会从旧位置复制数据;复制的金额是旧尺寸或新尺寸,以较小者为准。

char * ptr = malloc(sizeof(char) * 7);
int i;
for(i = 0;i<7;i++){
    ptr[i]= "pointer"[i];
}
puts(ptr);

这有未定义的行为。 puts需要指向字符串的指针,字符串需要空字符'\0'才能终止它。因此,对于长度为7个字符的字符串,您需要分配8个字节。 (一旦您完成了这项工作,您可以使用strcpy复制数据。)

似乎可以正常工作,因为恰好在分配的内存末尾的位置恰好是一个空字符。

ptr = realloc(ptr,sizeof(char) * 3);
puts(ptr);

更多未定义的行为。在realloc调用ptr指向(至少)3个字节的内存之后。由于新尺寸小于旧尺寸,系统能够将新块放在与旧尺寸相同的位置;它只是标志着它的尺寸较小。

所以&#34;运气&#34;,ptr指向一系列字符:

'p', 'o', 'i', 'n', 't', 'e', 'r', '\0'

但只有前3个字节在内存中才能安全访问。

realloc 可能分配了一大块新内存,而超过该块结尾的数据包含的内容不仅仅是{{1} }。

还有一件事:'n', 't', 'e', 'r', '\0'如果无法分配内存,则返回空指针。即使您试图缩小分配的内存,也应该始终检查它。如果realloc失败,它会留下原来分配的内存;您应该考虑将结果分配给不同的指针对象,这样您仍然可以访问原始内存。 (除非你打算终止程序;否则它并不重要。)