Где вы написали:
/* Allocate new space for a copy of the input parameter "Atoms" */
atoms = (struct Atom *) malloc(sizeof(struct Atom) * numAtoms);
/* Immediately lose track of the pointer to that space, once was stored
in atoms, now being lost. */
atoms = (*amino).atoms;
Я думаю, что ваше намерение должно быть таким:
/* Allocate new space for a copy of the input parameter "Atoms" */
atoms = (struct Atom *)malloc(sizeof(struct Atom) * numAtoms);
/* Copy the input parameter into the newly-allocated memory. */
for (i = 0; i < numAtoms; i++)
atoms[i] = (*amino).atoms[i];
, которое также может быть записано как:
/* Allocate new space for a copy of the input parameter "Atoms" */
atoms = (struct Atom *)malloc(sizeof(struct Atom) * numAtoms);
/* Copy the input parameter into the newly-allocated memory. */
memcpy(atoms, (*amino).atoms, sizeof(struct Atom) * numAtoms);
В C нет встроенного оператора равенства (=
) для копирования массивов, как вы, похоже, и предполагали.Вместо этого вы теряете указатель на выделенную память, ранее сохраненную в переменной atoms
, и затем начинаете первую итерацию цикла с atoms
, указывающим на «входную копию» массива атомов.
Часть проблемы заключается в том, что вы вызываете
free
в памяти, но затем вы продолжаете обращаться к указателю на эту освобожденную память.Вы не должны иметь доступ к указателям на освобожденную память.Чтобы избежать этого, замените все ваши бесплатные звонки на:
#ifdef free
# undef free
#endif
#define free(f) freeptr(&f)
void freeptr(void **f)
{
/* This function intentionally segfaults if passed f==NULL, to alert
the programmer that an error has been made. Do not wrap this code
with a check "if (f==NULL)", fix the problem where it is called.
To pass (*f==NULL) is a harmless 'no-op' as per the C standard
free() function.
If you must access the original, built-in free(), use (free)() to
bypass the #define macro replacement of free().
*/
(free)(*f); /* free() must accept NULL happilly; this is safe. */
*f = NULL; /* Set the pointer to NULL, it cannot be used again. */
}
На данный момент вы можете просто вырезать и вставить приведенный выше код где-нибудь в верхней части вашей программы.Хорошее место - после окончательной директивы #include
, но это должно происходить на уровне файлов и до вашего первого использования free()
в коде.
После перекомпиляции кода вы найдете BusОшибки и Сегментация Нарушения сразу после вас free(atom)
.Это правильно, и цель freeptr()
- привести ваш код к немедленному падению, а не к текущей ситуации, когда ваш код неправильно использует указатели и приводит к проблемам, которые вам очень трудно отлаживать.
наконец, исправьте распределение памяти, определенно транспонируйте строки:
bonds = (int *) malloc(sizeof(int));
free(bonds);
, которые должны выглядеть следующим образом:
free(bonds);
bonds = (int *) malloc(sizeof(int));
Вы используете аргумент diff
, как будто вы передаете вмассив не менее трех (3) элементов.Вы должны убедиться, что вызывающая сторона передает достаточно памяти.
При выделении
bonds
вы должны выделить память не для одного (1) целого числа, а для такого количества целых чисел, как
numBonds
:
free(bonds);
bonds = (int *) malloc(sizeof(int) * numBonds);
или, что лучше для большинстваC-кодеры:
free(bonds);
/* The calloc function performs the multiplication internally, and
nicely zero-fills the allocated memory. */
bonds = calloc(numBonds, sizeof(int));
Вам нужно будет исправить распределение atoms
, чтобы выделить правильное число элементов.В настоящее время вы также выделяете только один элемент памяти размером sizeof(struct Atom)
.Массив таких элементов требует умножения размера одного элемента на количество элементов.
Функция calloc()
удобна тем, что выделяет для вас массив и инициализирует содержимое всех элементов до нуля.,malloc()
ничего не делает для инициализации возвращенной памяти и может привести к непредсказуемым значениям, распространяющимся в вашей программе.Если вы используете malloc()
вместо calloc()
, вы должны позаботиться об инициализации элементов массива.Даже при использовании calloc()
необходимо инициализировать любые ненулевые элементы.
Обратите внимание, что я удалил приведение из возвращаемого значения malloc
.Если вы пишете C-код, вы должны компилировать его как C-код.Компилятор не будет жаловаться на отсутствие приведения из void *
, если вы не компилируете в режиме C ++.Исходные файлы C должны заканчиваться .c
расширениями файла, а не .cpp
.
Как указал Уолтер Мундт, вы случайно вызываете free()
для члена одного из ваших входных параметров, которыйВы присвоили указатель atoms
.Вам придется исправить это самостоятельно;вышеприведенный freeptr()
не выделит для вас эту ошибку.
Другие написали, что вы не можете использовать printf()
, чтобы надежно определить, где происходит сбой вашей программы.Вывод printf()
буферизуется, и его появление задерживается.
Лучше всего использовать gdb
, чтобы определить точную линию, в которой происходит сбой вашей программы.Вам не нужно будет учить какие-либо команды gdb
, чтобы сделать это, если вы скомпилируете свой код для отладки.
В отсутствие этого замените:
printf("Program ran to point A.\n");
на:
fprintf(stderr, "Program ran to point A.\nPress return.\n");
fflush(stderr); /* Force the output */
fflush(stdin); /* Discard previously-typed keyboard input */
fgetc(stdin); /* Await new input */
fflush(stdin); /* Discard unprocessed input */
В целом, я предлагаю вам не использовать язык C в настоящее время.В наши дни компьютеры настолько быстры, что я бы спросил, почему вы в первую очередь рассматривали C.
Не поймите меня неправильно;Я люблю язык Си.Но С не для всего.C отлично подходит для операционных систем, встроенных систем, высокопроизводительных вычислений и других случаев, когда основным препятствием для успеха является отсутствие низкоуровневого доступа к вычислительной технике.быть ученым или инженером.Я рекомендую вам изучить и использовать Python.Python предоставляет легко читаемые, легко проверяемые программы, которыми вы можете поделиться со своими коллегами-химиками или инженерами.C не позволяет быстро писать надежный код, как это делает Python.В этом маловероятном будущем событии, когда Python недостаточно быстр для ваших целей, есть другие решения, к которым вы тогда будете готовы.