Освобождение массива после того, как он был записан 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 ответ:
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-го свободного блока является мусором.
- вычислите размер большего свободного блока из других блоков. Если один из них содержит мусор, мусор будет использоваться для вычисления нового, большего размера свободного блока, и путаница будет совершенной.