Munmap_chunk():无效指针,已中止(核心已转储),realloc():下一个大小无效
Munmap_chunk(): invalid pointer, Aborted (core dumped), realloc(): invalid next size
我正在编写代码,用户可以在其中输入 Minesweeper 的字段,其中 '.'
是空字段,'*'
是炸弹。程序将从输入中读取字段的大小,然后 打印整个游戏字段 ,其中字段 '.'
被替换为该字段周围的炸弹数量,如果该字段没有任何它打印 '.'
,如果该字段是 '*'
,它只打印 '*'
。
我们不知道输入(游戏场)有多大。 输入以 EOF 结束。我的程序适用于 "normal"(小)输入,例如 10x10 游戏场、50x50 游戏场、20x4 游戏场等。我将输入输入 arr,然后将每个索引复制到 arr2,这样我就可以得到另一个输入 arr 并且我不会丢失之前的输入。 两个数组都是一维的。在 arr2 中,如果炸弹 (' * '
) 在它周围,我将索引值从 '.'
更改为数字(即 2
)。
输入示例:
.*.
*.*
输出示例:
2*2
*3*
但是,当我尝试输入具有 216 行和 10 列 (216x10) 的游戏字段时,会发生以下情况:
- 如果代码和你看到的一样,程序会说:
realloc(): invalid next size.
Aborted (core dumped)
- 如果我在 realloc 中使用 &arr2,它表示相同。
- 如果我 删除 realloc 行它说:
munmap_chunk(): invalid pointer. Aborted (core dumped)
- 带有数字的打印游戏字段有 "correctly printed field" 和出现换行符或整行填充数字的部分。
Valgrind 表示没有内存泄漏或低输入错误。
由于我是内存管理和指针的新手,我无法找出问题出在哪里。
如果您提出问题并尝试帮助我,我将不胜感激。
我在这里显示的代码应该是有问题的部分(并且是程序的开头)。其余代码应该没问题,并基于这部分工作。
int main()
{
int err, size=200;
char *arr=NULL;
char *arr2=(char*)malloc(sizeof(char)*size);
size_t bufsize=0;
printf("Enter game field:\n");
while(true)
{
for (int i=0;i<size;i++)
{
err=getline(&arr,&bufsize,stdin);
if (i==(size-2))
{
size *= 3;
arr2=(char*)realloc(arr2,sizeof(char)*size);
}
for (int j=0;j<(err-1);j++)
{
arr2[l]=arr[j];
l++;
}
/*rest of the code*/
}
}
.
.
.
简答:
arr2
的分配对于大型板来说太小(总共 >200 字节),考虑在每次迭代时调整它的大小以处理未知大小。
// existing line
err=getline(&arr,&bufsize,stdin);
if ( err > 0 ) {
size += err ;
arr2 = realloc(arr2, size) ;
// Append arr to arr2.
}
或类似。
长答案:
存在编译错误 - 代码引用变量 'l'(在 arr2[] = arr[j] 中),但没有声明它(或指定它的值)。假设这是在 main
中声明的(或静态的)并初始化为零。
在每次迭代中,代码将输入行 arr
的内容附加到 arr2
。初始分配给 arr2 的只有 200 个字节。在大板 (216x10) 上,这将在迭代 20 中超出 arr2 的大小。
迭代 198 (i==size-2) 上的分配允许代码处理电路板总大小小于 200 字节(10x10,...)的小问题。
Valgrind:
在我的机器 (Mint 19) 上,valgrid 正确识别了 216x10 板的缓冲区溢出:
==61030== Memcheck, a memory error detector
==61030== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==61030== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==61030== Command: ./a.out
==61030==
Enter game field:
==61030== Invalid write of size 1
==61030== at 0x10882A: main (gg.c:25)
==61030== Address 0x522d108 is 0 bytes after a block of size 200 alloc'd
==61030== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==61030== by 0x10878C: main (gg.c:9)
==61030==
我正在编写代码,用户可以在其中输入 Minesweeper 的字段,其中 '.'
是空字段,'*'
是炸弹。程序将从输入中读取字段的大小,然后 打印整个游戏字段 ,其中字段 '.'
被替换为该字段周围的炸弹数量,如果该字段没有任何它打印 '.'
,如果该字段是 '*'
,它只打印 '*'
。
我们不知道输入(游戏场)有多大。 输入以 EOF 结束。我的程序适用于 "normal"(小)输入,例如 10x10 游戏场、50x50 游戏场、20x4 游戏场等。我将输入输入 arr,然后将每个索引复制到 arr2,这样我就可以得到另一个输入 arr 并且我不会丢失之前的输入。 两个数组都是一维的。在 arr2 中,如果炸弹 (' * '
) 在它周围,我将索引值从 '.'
更改为数字(即 2
)。
输入示例:
.*.
*.*
输出示例:
2*2
*3*
但是,当我尝试输入具有 216 行和 10 列 (216x10) 的游戏字段时,会发生以下情况:
- 如果代码和你看到的一样,程序会说:
realloc(): invalid next size. Aborted (core dumped)
- 如果我在 realloc 中使用 &arr2,它表示相同。
- 如果我 删除 realloc 行它说:
munmap_chunk(): invalid pointer. Aborted (core dumped)
- 带有数字的打印游戏字段有 "correctly printed field" 和出现换行符或整行填充数字的部分。
Valgrind 表示没有内存泄漏或低输入错误。
由于我是内存管理和指针的新手,我无法找出问题出在哪里。 如果您提出问题并尝试帮助我,我将不胜感激。
我在这里显示的代码应该是有问题的部分(并且是程序的开头)。其余代码应该没问题,并基于这部分工作。
int main()
{
int err, size=200;
char *arr=NULL;
char *arr2=(char*)malloc(sizeof(char)*size);
size_t bufsize=0;
printf("Enter game field:\n");
while(true)
{
for (int i=0;i<size;i++)
{
err=getline(&arr,&bufsize,stdin);
if (i==(size-2))
{
size *= 3;
arr2=(char*)realloc(arr2,sizeof(char)*size);
}
for (int j=0;j<(err-1);j++)
{
arr2[l]=arr[j];
l++;
}
/*rest of the code*/
}
}
.
.
.
简答:
arr2
的分配对于大型板来说太小(总共 >200 字节),考虑在每次迭代时调整它的大小以处理未知大小。
// existing line
err=getline(&arr,&bufsize,stdin);
if ( err > 0 ) {
size += err ;
arr2 = realloc(arr2, size) ;
// Append arr to arr2.
}
或类似。
长答案:
存在编译错误 - 代码引用变量 'l'(在 arr2[] = arr[j] 中),但没有声明它(或指定它的值)。假设这是在 main
中声明的(或静态的)并初始化为零。
在每次迭代中,代码将输入行 arr
的内容附加到 arr2
。初始分配给 arr2 的只有 200 个字节。在大板 (216x10) 上,这将在迭代 20 中超出 arr2 的大小。
迭代 198 (i==size-2) 上的分配允许代码处理电路板总大小小于 200 字节(10x10,...)的小问题。
Valgrind:
在我的机器 (Mint 19) 上,valgrid 正确识别了 216x10 板的缓冲区溢出:
==61030== Memcheck, a memory error detector
==61030== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==61030== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==61030== Command: ./a.out
==61030==
Enter game field:
==61030== Invalid write of size 1
==61030== at 0x10882A: main (gg.c:25)
==61030== Address 0x522d108 is 0 bytes after a block of size 200 alloc'd
==61030== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==61030== by 0x10878C: main (gg.c:9)
==61030==