我正在尝试创建一个指向char指针的指针,我可以轻松地添加新元素(字符串)。当我想添加新项目时,我使用 malloc 创建前2个维度和 realloc 。我使用和不使用 realloc 编写代码,我得到了相同的结果。这是预期的/正常的行为吗?
使用realloc :
char **p; // create pointer to char pointer
p = malloc(sizeof(char*) * 2); // allocate 2 dimensions
p[0] = "ab";
p[1] = "cd";
void* resizedP = (void*)realloc(p, sizeof(char*) * 4); // resize array
p = (char**)resizedP;
p[2] = "ef";
p[3] = "gh";
printf("%s \n", p[0]); // prints ab
printf("%s \n", p[1]); // prints cd
printf("%s \n", p[2]); // prints ef
printf("%s \n", p[3]); // prints gh
free(p);
没有realloc :
char **p;
p = malloc(sizeof(char*) * 2);
p[0] = "ab";
p[1] = "cd";
p[2] = "ef";
p[3] = "gh";
printf("%s \n", p[0]); // prints ab
printf("%s \n", p[1]); // prints cd
printf("%s \n", p[2]); // prints ef
printf("%s \n", p[3]); // prints gh
free(p);
答案 0 :(得分:8)
绝对有必要调用realloc()
来调整malloc()
获得的内存块的大小。您通过访问已分配给程序的内存块的边界来调用未定义的行为。
在您分配的内存块之后可能会有一些重要数据,您的第二个代码段将会运行。如果程序甚至因为越界错误而尝试访问另一个进程中的内存块,操作系统会大声抱怨(导致分段错误)。
无法保证您的第二个代码段(没有realloc()
)将来不会崩溃或以其他方式失败。这次碰巧工作了。
答案 1 :(得分:4)
在你的情况下,它可能巧合。例如,您的C库的malloc()
可能会决定将您的分配大小填充为恰好为>= 2*sizeof(void*)
的某个数字。
但是,理论上,没有什么可以阻止后续malloc
返回恰好位于p[2]
的字节。也没有什么可以阻止malloc
返回一个值,在你请求的大小之后,操作系统没有将任何页面映射到地址空间。因此,您不应该依赖此行为。如果没有分配合适的金额,请不要写入p[2]
,因为这可能导致以下任何一种情况:
答案 2 :(得分:3)
尝试通过 valgrind 或使用 -fstack-protector 编译器开关运行第二个选项。您可能会获得有关为什么In silico的答案是正确的更多信息。
答案 3 :(得分:2)
假设您的p
是一辆可容纳20人的公共汽车。
你试图把30个人放进去(没有放大)。有时它会起作用,如果它们不胖的话 ......
关于C
,未定义的行为。任何事情都可能发生。你刚才不走运,它“有效”。
简而言之:不要那样做!
答案 4 :(得分:1)
哇,不要那个男人!这是有道理的,它只不过是麻烦。
首先,p不是一个数组,它是一个指针,您可以通过检查sizeof(p)
来看到它,它将始终返回4或8,具体取决于您运行的是32位还是64位系统。 / p>
指针指向内存中的位置,因此如果您尝试打印指针,您将获得一个内存地址,例如32位计算机上的0x0B32D2F1,当您调用其中一个*alloc
函数时,处理器找到您请求的大小的空闲内存块,并将其分配给您的程序。
你所做的是访问和编辑尚未分配给你的内存,虽然很容易,没有什么能阻止你这样做,但这很糟糕,因为内存可能被分配给不同的程序,然后是用户当你崩溃他的其他程序时会恨你。简而言之,总是会分配您将使用的记忆! ALWAYSS!
哦,是的,那么处理器可能会将您正在使用的未分配内存分配给另一个程序,这将使您的程序混乱。