当realloc移动内存块时如何更新其他指针?

20

realloc函数可能会将内存块移动到新的位置,此时返回新的位置。

那么这是否意味着如果我这样做:

void foo() {

        void* ptr = malloc( 1024 );

        unsigned char* cptr = ( unsigned char* )ptr+256;

        ptr = realloc( ptr, 4096 );
}

如果realloc移动了块,那么cptr可能会变为无效指针?

如果是这样的话,那么realloc会发出任何信号表明它将移动块,以便我可以做些什么来防止cptr失效呢?


这是一个很好的问题,我给它加上+1,因为它强调了涉及realloc的基本学习曲线。 - t0mm13b
5个回答

9
是的,realloc移动块时,cptr将变得无效!而且,没有提到向您发出信号告知它正在移动内存块。顺便说一句,你的代码看起来有点可疑...继续阅读...请查看我对另一个问题的答案并仔细阅读如何使用realloc的代码。普遍的共识是,如果你这样做:
void *ptr = malloc(1024);
/* later on in the code */ ptr = realloc(ptr, 4096);
/* BAM! if realloc failed, your precious memory is stuffed! */
解决这个问题的方法是使用一个临时指针,并像下面这样使用:
void *ptr = malloc(1024);
/* later on in the code */
void *tmp = realloc(ptr, 4096);
if (tmp != null) ptr = tmp;
编辑:感谢Secure指出我在早些时候打字时出现的错误。

不行!你不能这样做...这是编译器/链接器/运行时相关的。而且,你也不能保留旧地址,因为程序运行期间堆内存会被分段。简而言之,你无法绝对固定旧地址,因为指针的本质就是基于动态寻址的...并且你也不能撤销realloc操作... - t0mm13b
这是我见过的最无用的malloc返回值转换。为什么你要转换malloc的返回值,但不转换realloc的返回值呢? - Secure
@tommieb75,我猜你指的是使用char作为malloc返回类型的ANSI编译器之前的编译器。否则,你的第二条评论就没有意义了,将void强制转换为void*... - Secure
@zajcev:我很好奇,我能看到那个信息的来源吗?因为这对我来说是新的东西。谢谢你分享这有趣的片段… :) - t0mm13b
如果新指针与旧指针不同,则内存已被移动。因此会发出信号。 - ceving
显示剩余8条评论

5
这有点晚了,但是解决这个问题的方法(没有人提到)不是使用指向需要分配的已分配块的指针。相反,使用从基指针开始的整数值偏移量或(更好地)使用结构体类型和成员元素来寻址已分配对象中的特定位置。

真希望在写完我的当前任务之前能想到这个。 我认为这也是解决zajcev的OP问题的一部分,可以解释他可以采取什么措施。 - gone

4

是的,如果realloc移动了块,cptr将变得无效。

不,没有信号。您需要将返回值与原始的ptr位置进行比较。


3

是的。

最好的做法是在重新分配内存之前和之后比较指针,看它是否已经移动。你不应该将指针分配给偏移值,而是应该存储偏移量,然后使用它来索引原始操作符。

例如:

不要这样写: void* newPtr = ptr + 10; *newPtr = something;

而应该这样写: int new = 10; ptr[new] = something;


2
是的,如果realloc移动了块,cptr就会变得无效。

抱歉大声喊叫,但这有助于让简短的答案通过最小长度要求。 - bmargulies

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接