Ваша проблема здесь, в cellGetNeighbors
:
struct cell cn[8];
Вы выделяете cn
в стеке, поэтому, когда ваша функция cellGetNeighbors
завершится и вернется, значение cn
(версия cellGetNeighbors
) больше не будет действительной, а cn
в cellMinNeighbor
будет указывать на часть стека, которая используется для чего-то другого.
У вас есть два простых варианта:
- Передайте массив из восьми
struct cell
в cellGetNeighbors
, чтобы вызывающий отвечал за выделение этой памяти. - Выделите
cn
в куче (то есть malloc
) внутри cellGetNeighbors
и верните его как есть.Вызывающая сторона, конечно, должна будет free
возвращать cellGetNeighbors
значение, когда оно будет завершено (и этот факт должен быть задокументирован как часть cellGetNeighbors
интерфейса).
Я бы порекомендовал второй вариант, и я бы порекомендовал создать отдельную функцию cellFree
, чтобы правильно освободить одну ячейку.Функция cellFree
- хорошая идея, потому что в вашем struct cell
есть указатель, и этот указатель необходимо освободить.Это, конечно, еще сложнее, если вам когда-либо понадобится использовать массив, который не имеет ровно восьми элементов;если это произойдет, вам придется также вернуть размер массива, добавив дополнительный аргумент-указатель к getCellNeighbors
.Если дело доходит до этого момента, вам нужно добавить отдельную структуру:
struct cells {
int n; /* How many cells there are */
struct cell *items; /* The cells themselves */
}
и набор функций для выделения и освобождения этих новых структур.
Я предполагаю, чтоу вас есть аналогичные проблемы стека и кучи с cellCalculateKey
.
И вам не нужно этого делать:
struct cell *cptr = &cn[0];
cellPrintData(&cn[2]);
return cptr;
Массив cn
будет затухать до указателябез вашего вмешательства, это нормально:
cellPrintData(&cn[2]);
return cn;
Более того, поскольку я уже пишу здесь книгу, вам не нужно разыгрывать возврат из malloc
(или calloc
или realloc
или что-либо еще, что возвращает void *
) в C и это может скрыть проблемы.Итак, где вы говорите это:
struct cell *c2 = (struct cell *) malloc(sizeof(struct cell));
/* ... */
c2->keys = (struct keys *) malloc(sizeof(struct key));
вы должны просто сказать:
struct cell *c2 = malloc(sizeof(struct cell));
/* ... */
c2->keys = malloc(sizeof(struct key));
И еще одна вещь, у вас есть утечка памяти прямо здесь:
for(i = 0; i < 8; i++) {
cn[i] = *cellDuplicate(c);
}
Память, которую cellDuplicate
выделяет для нового struct cell
, просочилась.Вам было бы лучше с чем-то более похожим на это:
for(i = 0; i < 8; i++) {
cellDuplicateContent(c, &cn[i]);
}
И cellDuplicateContent
будет просто копировать отдельные элементы и, конечно, выделять данные для keys
, так как это указатель (то есть cellCopyValues
плюс выделение keys
).