双字符指针 c 的简单多重重新分配
simple multiple reallocation of double char pointer c
我试图在一个较大的程序中动态地重新分配一个双字符指针,但我总是收到该错误 "realloc(): invalid next size",所以我写了一个较小的测试来向你们展示我的确切问题:
我的小测试:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(void){
char **buf = malloc(sizeof(char*));
for(int i = 0; i < 20; i++){
buf[i] = malloc(sizeof(char) * 6);
strcpy(buf[i], "hallo");
printf("%s\n", buf[i]);
if( (realloc(buf, sizeof(char*) * (i+1))) == NULL) exit(-1);
}
return 0;
}
这总是在第 4 次重新分配时崩溃并显示完整的错误消息:
Error in `./myTest': realloc(): invalid next size: 0x0000000001cb2010 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f450a4a97e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x834aa)[0x7f450a4b54aa]
/lib/x86_64-linux-gnu/libc.so.6(realloc+0x179)[0x7f450a4b6839]
./myTest[0x40069c]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f450a452830]
./myTest[0x400529]
======= Memory map: ========
00400000-00401000 r-xp 00000000 08:01 663159
/home/qbongo/BS-PK-2017/10_pk/myTest
00600000-00601000 r--p 00000000 08:01 663159
/home/qbongo/BS-PK-2017/10_pk/myTest
00601000-00602000 rw-p 00001000 08:01 663159
/home/qbongo/BS-PK-2017/10_pk/myTest
01cb2000-01cd3000 rw-p 00000000 00:00 0 [heap]
7f4504000000-7f4504021000 rw-p 00000000 00:00 0
7f4504021000-7f4508000000 ---p 00000000 00:00 0
7f450a21c000-7f450a232000 r-xp 00000000 08:01 398530
/lib/x86_64-linux-gnu/libgcc_s.so.1
7f450a232000-7f450a431000 ---p 00016000 08:01 398530
/lib/x86_64-linux-gnu/libgcc_s.so.1
7f450a431000-7f450a432000 rw-p 00015000 08:01 398530
/lib/x86_64-linux-gnu/libgcc_s.so.1
7f450a432000-7f450a5f2000 r-xp 00000000 08:01 394742
/lib/x86_64-linux-gnu/libc-2.23.so
7f450a5f2000-7f450a7f2000 ---p 001c0000 08:01 394742
/lib/x86_64-linux-gnu/libc-2.23.so
7f450a7f2000-7f450a7f6000 r--p 001c0000 08:01 394742
/lib/x86_64-linux-gnu/libc-2.23.so
7f450a7f6000-7f450a7f8000 rw-p 001c4000 08:01 394742
/lib/x86_64-linux-gnu/libc-2.23.so
7f450a7f8000-7f450a7fc000 rw-p 00000000 00:00 0
7f450a7fc000-7f450a822000 r-xp 00000000 08:01 393312
/lib/x86_64-linux-gnu/ld-2.23.so
7f450aa07000-7f450aa0a000 rw-p 00000000 00:00 0
7f450aa20000-7f450aa21000 rw-p 00000000 00:00 0
7f450aa21000-7f450aa22000 r--p 00025000 08:01 393312
/lib/x86_64-linux-gnu/ld-2.23.so
7f450aa22000-7f450aa23000 rw-p 00026000 08:01 393312
/lib/x86_64-linux-gnu/ld-2.23.so
7f450aa23000-7f450aa24000 rw-p 00000000 00:00 0
7ffcc108f000-7ffcc10b0000 rw-p 00000000 00:00 0 [stack]
7ffcc1149000-7ffcc114b000 r--p 00000000 00:00 0 [vvar]
7ffcc114b000-7ffcc114d000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0
[vsyscall]
Aborted (core dumped)
通过调用 char **buf = malloc(sizeof(char*));
,您只分配了一个指针,而不是它们的数组。
const size_t items_count = 20;
char **buf = malloc(sizeof(char*) * items_count);
for(int i = 0; i < items_count; i++){
buf[i] = malloc(sizeof(char) * 6); // now we won't access array out of bounds here
// no need to realloc
应该是:
buf = realloc(buf, sizeof(char*) * (i+2));
- 您的代码只是丢弃了
realloc
. 的结果
- 如果在迭代结束时进行分配,则需要分配
(i+2)
。
我假设这不是您的实际代码,但将 realloc
移动到循环顶部(检查 first example for realloc
on this page)会更有意义,例如:
for(int i = 0; i < 20; i++)
{
buf = realloc(buf, sizeof(char*) * (i+1));
if (buf == NULL)
exit(-1);
...
}
(更新)
根据下面@coderredoc 的评论,虽然 exit
将释放与该进程关联的所有内存,但请记住,良好的编程习惯是释放先前分配的指针,以防 realloc
失败:
char **buf = malloc(sizeof(char*));
for (int i = 0; i < 20; i++)
{
// try to realloc
{
char ** larger = realloc(buf, sizeof(char*) * (i + 1));
if (larger)
{
buf = larger;
}
else
{
// realloc failed, we might need to free individual items
// if we are not going to use them anymore
for (int k = 0; k < (i - 1); k++) free(buf[k]);
// we should free previous buff also
free(buff);
// we can exit, or break the loop, or whatever
exit(-1);
}
}
// do stuff here
...
}
我发现您的代码中有 2 个错误。
您没有在 buf
中存储 realloc
返回的新地址。当所需的新 space 不可用时,realloc
会在内存中的其他地方分配一个新的 space。
您的循环从 i = 0
开始,因此您第一次到达 realloc
时,您应该分配两个元素:i+2
而不是 i+1
我试图在一个较大的程序中动态地重新分配一个双字符指针,但我总是收到该错误 "realloc(): invalid next size",所以我写了一个较小的测试来向你们展示我的确切问题:
我的小测试:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(void){
char **buf = malloc(sizeof(char*));
for(int i = 0; i < 20; i++){
buf[i] = malloc(sizeof(char) * 6);
strcpy(buf[i], "hallo");
printf("%s\n", buf[i]);
if( (realloc(buf, sizeof(char*) * (i+1))) == NULL) exit(-1);
}
return 0;
}
这总是在第 4 次重新分配时崩溃并显示完整的错误消息:
Error in `./myTest': realloc(): invalid next size: 0x0000000001cb2010 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f450a4a97e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x834aa)[0x7f450a4b54aa]
/lib/x86_64-linux-gnu/libc.so.6(realloc+0x179)[0x7f450a4b6839]
./myTest[0x40069c]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f450a452830]
./myTest[0x400529]
======= Memory map: ========
00400000-00401000 r-xp 00000000 08:01 663159
/home/qbongo/BS-PK-2017/10_pk/myTest
00600000-00601000 r--p 00000000 08:01 663159
/home/qbongo/BS-PK-2017/10_pk/myTest
00601000-00602000 rw-p 00001000 08:01 663159
/home/qbongo/BS-PK-2017/10_pk/myTest
01cb2000-01cd3000 rw-p 00000000 00:00 0 [heap]
7f4504000000-7f4504021000 rw-p 00000000 00:00 0
7f4504021000-7f4508000000 ---p 00000000 00:00 0
7f450a21c000-7f450a232000 r-xp 00000000 08:01 398530
/lib/x86_64-linux-gnu/libgcc_s.so.1
7f450a232000-7f450a431000 ---p 00016000 08:01 398530
/lib/x86_64-linux-gnu/libgcc_s.so.1
7f450a431000-7f450a432000 rw-p 00015000 08:01 398530
/lib/x86_64-linux-gnu/libgcc_s.so.1
7f450a432000-7f450a5f2000 r-xp 00000000 08:01 394742
/lib/x86_64-linux-gnu/libc-2.23.so
7f450a5f2000-7f450a7f2000 ---p 001c0000 08:01 394742
/lib/x86_64-linux-gnu/libc-2.23.so
7f450a7f2000-7f450a7f6000 r--p 001c0000 08:01 394742
/lib/x86_64-linux-gnu/libc-2.23.so
7f450a7f6000-7f450a7f8000 rw-p 001c4000 08:01 394742
/lib/x86_64-linux-gnu/libc-2.23.so
7f450a7f8000-7f450a7fc000 rw-p 00000000 00:00 0
7f450a7fc000-7f450a822000 r-xp 00000000 08:01 393312
/lib/x86_64-linux-gnu/ld-2.23.so
7f450aa07000-7f450aa0a000 rw-p 00000000 00:00 0
7f450aa20000-7f450aa21000 rw-p 00000000 00:00 0
7f450aa21000-7f450aa22000 r--p 00025000 08:01 393312
/lib/x86_64-linux-gnu/ld-2.23.so
7f450aa22000-7f450aa23000 rw-p 00026000 08:01 393312
/lib/x86_64-linux-gnu/ld-2.23.so
7f450aa23000-7f450aa24000 rw-p 00000000 00:00 0
7ffcc108f000-7ffcc10b0000 rw-p 00000000 00:00 0 [stack]
7ffcc1149000-7ffcc114b000 r--p 00000000 00:00 0 [vvar]
7ffcc114b000-7ffcc114d000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0
[vsyscall]
Aborted (core dumped)
通过调用 char **buf = malloc(sizeof(char*));
,您只分配了一个指针,而不是它们的数组。
const size_t items_count = 20;
char **buf = malloc(sizeof(char*) * items_count);
for(int i = 0; i < items_count; i++){
buf[i] = malloc(sizeof(char) * 6); // now we won't access array out of bounds here
// no need to realloc
应该是:
buf = realloc(buf, sizeof(char*) * (i+2));
- 您的代码只是丢弃了
realloc
. 的结果
- 如果在迭代结束时进行分配,则需要分配
(i+2)
。
我假设这不是您的实际代码,但将 realloc
移动到循环顶部(检查 first example for realloc
on this page)会更有意义,例如:
for(int i = 0; i < 20; i++)
{
buf = realloc(buf, sizeof(char*) * (i+1));
if (buf == NULL)
exit(-1);
...
}
(更新)
根据下面@coderredoc 的评论,虽然 exit
将释放与该进程关联的所有内存,但请记住,良好的编程习惯是释放先前分配的指针,以防 realloc
失败:
char **buf = malloc(sizeof(char*));
for (int i = 0; i < 20; i++)
{
// try to realloc
{
char ** larger = realloc(buf, sizeof(char*) * (i + 1));
if (larger)
{
buf = larger;
}
else
{
// realloc failed, we might need to free individual items
// if we are not going to use them anymore
for (int k = 0; k < (i - 1); k++) free(buf[k]);
// we should free previous buff also
free(buff);
// we can exit, or break the loop, or whatever
exit(-1);
}
}
// do stuff here
...
}
我发现您的代码中有 2 个错误。
您没有在
buf
中存储realloc
返回的新地址。当所需的新 space 不可用时,realloc
会在内存中的其他地方分配一个新的 space。您的循环从
i = 0
开始,因此您第一次到达realloc
时,您应该分配两个元素:i+2
而不是i+1