在MPI_Recv写入数组后释放数组

jsj*_*jsj 6 c malloc free mpi

我有一个malloc'd整数数组,我填写 MPI_Recv

MPI_Recv(d.current, n, MPI_INT, 0, TAG_CURRENT_ARRAY, MPI_COMM_WORLD, &status);
Run Code Online (Sandbox Code Playgroud)

我测试了d.current之前和之后的值MPI_Recv,它没有改变(这是正确的).

我的数据正确到达.

但是,如果我尝试free数据,我会收到一个错误:

*** Error in `./bin/obddhe-mpi': free(): invalid next size (fast): 0x0965e988 ***
Run Code Online (Sandbox Code Playgroud)

在接收完美之前,完全相同的免费.

即..这个作品:

free(d.current);
//MPI_Recv(d.current, n, MPI_INT, 0, TAG_CURRENT_ARRAY, MPI_COMM_WORLD, &status);
Run Code Online (Sandbox Code Playgroud)

这失败了:

MPI_Recv(d.current, n, MPI_INT, 0, TAG_CURRENT_ARRAY, MPI_COMM_WORLD, &status);
free(d.current);
Run Code Online (Sandbox Code Playgroud)

可能MPI_Recv会做什么使免费无效!?

glg*_*lgl 5

一个SSCCE将是非常有益的.

那就是说,我会尽力回答:

我有一个malloc'd整数数组,我用MPI_Recv填充

MPI_Recv(d.current, n, MPI_INT, 0, TAG_CURRENT_ARRAY, MPI_COMM_WORLD, &status);
Run Code Online (Sandbox Code Playgroud)

那个阵列有多大?你究竟是怎么malloc()回事?什么是n在这种情况下,它是如何与malloc()ED的大小?

您的观察结果表明这MPI_Recv()是发生此错误的原因.为了使这个错误发生,MPI_Recv()已写入超出malloc()ed内存区域的末尾,这是不允许的.这会使内存管理内部使用的链表或其后面的块大小或两者混乱,从而导致上述错误.

我已经在MPI_Recv之前和之后测试了d.current的值,它没有改变(这是正确的).

(应该如何?你将指针传递给函数,而不是它的地址.所以指针不能改变.)

但是,如果我尝试释放数据,我会收到错误:

*`./bin/obddhe-mpi'出错:free():下一个大小无效(快):0x0965e988*

在接收完美之前,完全相同的免费.

这是我上面写的内容的另一条线索:你使用的块后面的meory已被释放,并包含指向下一个空闲区域的指针.如果你free()的内存,库试图合并空闲块,其中第二个被损坏,导致此错误.

想象一下,你有以下情况:

  • 您的内存管理器会根据其长度预先设置每个内存块,无论是空闲还是分配.
  • 空闲块在它们开始时具有下一个空闲块的地址 - 这是我提到的链接列表.
  • 您分配的块前面加上其长度,后跟
    • 一个空闲块,前面有它的长度,如果没有下一个空闲块,则包含下一个空闲块的地址.

然后,如果您在内存块的末尾写入,则将触及并篡改下一个块的长度和内容.

这对任何事都没有影响 - 直到现在.

但是如果你调用free()你的块,那么这个块将与之后的空闲块合并.

为此,必须执行以下操作:

  • 遍历链表以查找相邻的空闲块 - 这可能导致此错误,因为第二个空闲块的"下一个"指针是垃圾.
  • 计算其他块中较大空闲块的大小.如果其中一个包含垃圾,垃圾将用于计算新的,更大的空闲块大小,并且混乱是完美的.