【问题标题】:Munmap_chunk(): invalid pointer, Aborted (core dumped), realloc(): invalid next sizeMunmap_chunk(): 无效指针, Aborted (core dumped), realloc(): 无效的下一个大小
【发布时间】:2019-11-20 22:46:04
【问题描述】:

我正在编写代码,用户输入 Minesweeper 的字段,其中'.' 是空字段,'*' 是炸弹。程序将从输入中读取字段的大小,并打印整个游戏字段,其中 '.' 字段被该字段周围的炸弹数量替换,如果该字段没有任何内容,则打印'.',如果该字段为'*',则仅打印'*'

我们不知道输入(游戏领域)会有多大输入以 EOF 结束。我的程序适用于“正常”(小)输入,例如 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)
  • 带有数字的打印游戏字段具有“正确打印的字段”以及出现换行符或整行填充数字的部分。

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*/
            }
      }

.
.
.

【问题讨论】:

  • 关于:char *arr2=(char*)malloc(sizeof(char)*size); 这有几个问题。建议不要详细说明:char *arr2 = NULL; char *temp = realloc( arr2, size );,然后是:if( ! arr2 ) { perror( "calloc for arr2 failed" ); exit( EXIT_FAILURE ); } else { arr2 = temp;}
  • 变量l在哪里初始化?
  • 通过getline()读入的行内容的预期是什么?该行内容的验证在哪里?

标签: c arrays pointers malloc realloc


【解决方案1】:

简答:

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。给定仅 200 字节的初始分配给 arr2。在大板 (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== 

【讨论】:

  • 非常感谢您解释为什么它不起作用,它帮助我理解了问题并感谢给出的解决方案!这修复了我在大型游戏领域运行的程序!非常感谢!
猜你喜欢
  • 2020-08-29
  • 2020-08-04
  • 2020-12-27
  • 2018-08-23
  • 1970-01-01
  • 2014-10-13
  • 2015-01-22
相关资源
最近更新 更多