realloc会改变指针地址吗?

3

以这段代码为例:

Struct* allocSomething(void) {
    int n; 
    Struct *something = malloc(n*sizeof(Struct));
    return something;
}

Struct* reallocSomething(Struct **s) {
    int n;
    Struct *something = realloc(*s, (n*sizeof(int)) - 1 * sizeof(Struct));
    return something;
}

int main() {
    Struct *point = allocSomething();
    //code does something...
    point = reallocSomething();
    free(point);
}

我的问题是,在调用 reallocSomething 后,point 的地址是否仍然是由 allocSomething 返回的地址?例如,如果 point 的地址为 0x01,当这个指针被 reallocSomething 重新分配时,那个地址是否仍然是 0x01

3
编译器警告是你的朋友,务必启用并认真对待它们!还要阅读文档。 - too honest for this site
3个回答

9

以下是realloc的手册页面内容:

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

....

realloc() returns a pointer to the newly allocated memory, which is suitably aligned for any kind of variable and may be different from ptr, or NULL if the request fails. If size was equal to 0, either NULL or a pointer suitable to be passed to free() is returned. If realloc() fails the original block is left untouched; it is not freed or moved.

由于realloc函数可能会将已分配的内存移动到新位置,因此您需要考虑这一点。


3
不要指望它会一直停留在同一个地址。系统允许基于任何原因将整个内存块移动到不同的地址。虽然你正在请求的内存块更小,应该逻辑上适合前一个分配所空出的空间,但这不是一个原子操作,任何中断或时间共享都可能使其他内容占用该内存空间。也许您正在使用的系统还有其他花招,但从标准角度来看,不要指望地址会保持不变。当然也不要期望它会改变。

3
缺乏原子性与任何事情有什么关系? - EOF
这意味着调度程序可以在realloc调用中间中断程序并让其他东西运行。你知道,如果他的系统有这样的功能。如果有其他东西正在运行,它可以malloc并获取地址。我试图解释为什么系统会给他一个新地址而不是保留旧地址。 - Philip
3
其他程序不能看到相同的内存(除非它们使用共享内存,这不是由[m/c/re]alloc()处理而是由实现定义的原语(如mmap()))。其他线程可能会看到realloc()调用的非原子性,但只有在分配被交给另一个线程,然后在realloc()调用完成之前交还回来时才会出现此问题。由于这将需要不必要的完全复制和额外的内存,因此这只会在疯狂的实现中成为问题。认清事实,原子性对于这个问题是一个虚假的引子。 - EOF

0

从标准的角度来看,除非realloc失败,否则调用它的行为将不仅销毁由旧指针标识的存储,而且还会销毁旧指针本身。即使该指针的位模式恰好与新指针完全匹配,如果代码尝试通过检查其字节以外的方式访问旧指针,则编译器可能会表现出任意和反复无常的方式。

优质实现可能(并且可能应该)允许程序以某些超出标准要求的方式使用realloc(例如检查对象是否已移动,并重新计算标识其中某些部分的指针,但如果它没有移动,则不要费心进行此类计算),但是标准未定义指示可以指示它们是否支持此类结构的任何方法。


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