我正在写一个简短的程序,我需要首先malloc一个结构数组,如果用户询问malloc其他人,分配给他们相应的地址(我已经证明了这一点),但是当我realloc()其中一个重新分配侵入了其他人的空间,使他们无法使用......
我该怎么做才能避免这个问题?
答案 0 :(得分:1)
你正在做的是接触未定义的行为,至少是建议的。如果您需要对这样的内存块进行细粒度控制,则需要让系统的内存分配器为您提供一个大块来自行管理。
系统分配器在您的线程与您所做的任何系统或其他分配调用之间共享 - 例如strdup。 realloc发生的重新排序是由于realloc必须首先分配一个新块,然后在使旧块可用之前将旧数据复制到其中。但同样的问题将发生在应用程序生命周期的其他地方。
还有许多内存分配器策略。某些内存分配器实际上会分配比您请求的块稍大的块,并使用额外的空间来提供有关分配的信息。例如。当你要求16字节的内存时,他们会分配16 + sizeof(size_t)并存储他们返回给你的地址前面的分配大小:
void* malloc(size_t bytes)
{
uint32_t* block = _internal_malloc(bytes + sizeof uint32_t);
*block = bytes;
return &block[1]; // return a pointer to after the size we stored.
}
内存分配器也倾向于在操作系统版本之间进行更改,因此依赖它们的行为是一个非常糟糕的主意。
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
int main() {
char* a = malloc(32);
char* b = malloc(32);
char* s = strdup("hello");
char* c = malloc(32);
printf("a = %p, b = %p (a + 32 = %p), c = %p (b + 32 = %p)\n", a, b, a+32, c, b + 32);
// your code goes here
return 0;
}
输出:
a = 0x83af008, b = 0x83af030 (a + 32 = 0x83af028), c = 0x83af068 (b + 32 = 0x83af050)
你可以看到这些块是有序的但不是连续的,由于strdup,b和c之间也存在扩展的差距。
另一个可能影响排序的问题是免费池的碎片化。
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
int main() {
char* a = malloc(32);
char* b = malloc(32);
char* s = strdup("hello");
free(s);
char* c = malloc(32);
printf("a = %p, b = %p (a + 32 = %p), c = %p (b + 32 = %p)\n", a, b, a+32, c, b + 32);
// your code goes here
return 0;
}
在这里,即使我们free
d s,我们也会分配导致分割的分配,当我们要求相等或更小的分配时,我们只会返回该地址。