为什么不;realloc";将新元素分配给char指针时是否有必要?
我试图创建一个指向char指针的指针,我可以轻松地向其添加新元素(字符串)。当我想添加新项目时,我使用malloc创建前两个维度和realloc。我编写了带有和不带realloc的代码,得到了相同的结果。这是预期的/正常的行为吗为什么不;realloc";将新元素分配给char指针时是否有必要?,c,arrays,pointers,C,Arrays,Pointers,我试图创建一个指向char指针的指针,我可以轻松地向其添加新元素(字符串)。当我想添加新项目时,我使用malloc创建前两个维度和realloc。我编写了带有和不带realloc的代码,得到了相同的结果。这是预期的/正常的行为吗 使用realloc: char **p; // create pointer to char pointer p = malloc(sizeof(char*) * 2); // allocate 2 dimensions p[0] = "ab"
使用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);
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);
不带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);
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);
调用
realloc()
来调整通过malloc()
获得的内存块的大小是绝对必要的。您正在调用未定义的行为,方法是访问已分配给程序的内存块边界以外的内容
在分配的内存块之后,可能会有一些重要的数据,第二个代码段将在上面运行。如果程序甚至因为越界错误而试图在另一个进程中访问内存块,操作系统会大声抱怨(导致分段错误)
无法保证您的第二个代码段(没有
realloc()
)将来不会崩溃或失败。这次正好有用 假设您的p
是一辆可容纳20人的公共汽车
你试着把30个人放进去(不放大)。有时候,如果他们不胖的话,这是有效的
关于C
,这是未定义的行为。任何事情都有可能发生。你刚才运气不好,它“起作用了”
简言之:不要那样做 在你的情况下,这可能是巧合。例如,您的C库的
malloc()
可能决定将分配大小填充为某个数字,该数字恰好是=2*sizeof(void*)
然而,理论上,没有什么可以阻止后续的malloc
返回恰好位于p[2]
的字节。也没有什么可以阻止malloc
返回一个值,即在您请求的大小之后,操作系统没有将任何页面映射到地址空间。因此,你不应该依赖这种行为。在未分配正确金额的情况下,不要写信给p[2]
,因为这可能导致以下任何情况:
- 覆盖其他函数写入的值
- 其他一些功能可能会在以后覆盖您
- 您可能会在尝试访问它时崩溃
sizeof(p)
来看到这一点,它将始终返回4或8,这取决于您运行的是32位还是64位系统
指针指的是内存中的一个位置,因此如果您试图打印指针,您将获得一个内存地址,例如32位机器上的0x0B32D2F1。当您调用*alloc
函数之一时,处理器会找到一个与您请求的大小相同的空闲内存块,并将其分配给您的程序
您所做的是访问和编辑尚未分配给您的内存,虽然很容易做到,但没有什么可以阻止您这样做,但这是不好的,因为该内存可能分配给其他程序,然后当您使其他程序崩溃时,用户会恨恶您。简言之,始终分配要使用的内存!永远
哦,是的,那么处理器有可能会将您正在使用的未分配内存分配给另一个程序,这会弄乱您的程序。哦!我想要一个无限的记忆库!非常感谢你的回答!从技术上讲,它不能也不会在任何系统上运行另一个进程的内存,而该系统将SIGSEGV视为一个进程。更像是它可以引用一个未标记为写访问的段或一个没有映射到它的帧的页。@Novikov:是的,操作系统应该在运行另一个程序之前停止对它的内存访问。我已经编辑了我的文章,让它更清楚一点。谢谢你指出我对数组和指针的混淆。我编辑了我问题的标题。谢谢,我阅读了解释valgrind做什么以及如何工作的文档。我肯定会尝试它,但在另一个安装了Linux的盒子上。