Освобождение массива после того, как он был записан MPI Recv


У меня есть malloc'D массив целых чисел, которые я заполняю MPI_Recv

MPI_Recv(d.current, n, MPI_INT, 0, TAG_CURRENT_ARRAY, MPI_COMM_WORLD, &status);

Я проверил значение d.current как до, так и после MPI_Recv, и оно не меняется (что правильно).

Мои данные поступают правильно.

Однако, если я попытаюсь free данные, я получу ошибку:

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

Точно такой же свободный перед получением работает отлично.

То есть... Это Работает:

free(d.current);
//MPI_Recv(d.current, n, MPI_INT, 0, TAG_CURRENT_ARRAY, MPI_COMM_WORLD, &status);

Это Не Удается:

MPI_Recv(d.current, n, MPI_INT, 0, TAG_CURRENT_ARRAY, MPI_COMM_WORLD, &status);
free(d.current);

Что может MPI_Recv делать, что делает недействительным бесплатно!?

1 6

1 ответ:

A SSCCE было бы очень полезно.

Тем не менее, я постараюсь ответить как можно лучше:

У меня есть malloc'D массив целых чисел, которые я заполняю MPI_Recv

MPI_Recv(d.current, n, MPI_INT, 0, TAG_CURRENT_ARRAY, MPI_COMM_WORLD, &status);

Насколько велик этот массив? Как именно вы это сделали? Что такое n в данном случае и как это связано с размером malloc()Эд?

Ваши наблюдения показывают, что MPI_Recv() является причиной возникновения этой ошибки. Для того, чтобы эта ошибка произошла, MPI_Recv() написал после конца области памяти malloc()ed, что недопустимо. Это портит либо связанный список, используемый внутри системы управления памятью, либо размер блоков за ним, либо и то и другое, что приводит к указанной ошибке.

Я проверил значение D. current как до, так и после MPI_Recv, и оно не меняется (что правильно).

(как это должно быть? Вы передаете указатель на функцию, а не ее адрес. Таким образом, указатель не может измениться.)

Однако, если я попытаюсь чтобы освободить данные, я получаю ошибку:

* ошибка в `./bin / obddhe-mpi': free (): недопустимый следующий размер (быстрый): 0x0965e988 *

Точно такой же свободный перед получением работает отлично.

Это еще один ключ к тому, что я написал выше: меори за блоком, который вы используете, был освобожден и содержит указатель на следующую свободную область. Если вы free() ваша память, библиотека пытается объединить свободные блоки, второй из которых поврежден, что и привело к этой ошибке.

Представьте себе, что у вас есть следующая ситуация:

  • ваш менеджер памяти добавляет к каждому блоку памяти, будь то свободный или выделенный, его длину.
  • свободные блоки имеют адрес следующего свободного блока в их начале - это связанный список, который я упомянул.
  • ваш выделенный блок, предваряемый его длиной, сопровождается
    • свободный блок, предваряемый его длиной и содержащий адрес следующего свободного блока NULL, если следующего свободного блока нет.

Затем, если вы пишете после конца блока памяти, длина и содержание следующего блока будут затронуты и изменены.

Это ни на что не влияет - до сих пор.

Но если вы вызовете free() на вашем блоке, этот блок будет объединен со свободным блоком после него.

Для того чтобы сделать это, следующие действия должны произойти:

  • пройдите по связанному списку, чтобы найти соседние свободные блоки. - что уже может привести к этой ошибке, потому что "следующий" указатель 2-го свободного блока является мусором.
  • вычислите размер большего свободного блока из других блоков. Если один из них содержит мусор, мусор будет использоваться для вычисления нового, большего размера свободного блока, и путаница будет совершенной.