Я в настоящее время помогаю другу отладить программу его, который включает связанные списки. Его структура списка довольно проста:
typedef struct nodo{
int cantUnos;
char* numBin;
struct nodo* sig;
}Nodo;
У нас есть следующий фрагмент кода:
void insNodo(Nodo** lista, char* auxBin, int auxCantUnos){
printf("*******Insertando\n");
int i;
if (*lista) printf("DecInt*%p->%p\n", *lista, (*lista)->sig);
Nodo* insert = (Nodo*)malloc(sizeof(Nodo*));
if (*lista) printf("Malloc*%p->%p\n", *lista, (*lista)->sig);
insert->cantUnos = auxCantUnos;
insert->numBin = (char*)malloc(strlen(auxBin)*sizeof(char));
for(i=0 ; i<strlen(auxBin) ; i++)
insert->numBin[i] = auxBin[i];
insert->numBin[i] = '\0';
insert->sig = NULL;
Nodo* aux;
/* [etc] */
(Строки с дополнительным добавлением отступа были моим дополнением в целях отладки),
Это приводит ко мне следующее:
*******Insertando
DecInt*00341098->00000000
Malloc*00341098->2832B6EE
(*lista)->sig
ранее и сознательно установлен как NULL
, который проверяет до здесь и зафиксировал потенциальное переполнение буфера (он забыл копировать ПУСТОЙ разделитель во вставке-> ошеломляющий).
Я не могу думать о единственной причине, почему это произошло бы, ни у меня есть какая-либо идея о том, что еще я должен обеспечить как дальнейшая информация (Компилирующий на последнем стабильном MinGW в соответствии с полностью исправленным Windows 7, использование друга MinGW под Windows XP. На моей машине, по крайней мере, в только происходит когда GDB's, не присоединенный.)
Какие-либо идеи? Предложения? Возможные методы изгнания нечистой силы? (Текущий взлом копирует указатель сигнала на временную переменную, и восстановите его после malloc. Это повреждается так или иначе. Оказывается, что 2-й malloc повреждает его также. Интересно достаточно это сбрасывает сигнал к тому же самому значению как первое).
ОБНОВЛЕНИЕ: Спасибо за ответы. Относительно Node*
вещь, это фиксируется, но никакое изменение. По крайней мере, предотвращает потенциальные проблемы впоследствии. Строка, копирующая, не является проблемой, когда я уже зафиксировал всех пропавших без вести \0s сам. (Отметьте insertBin[i] = '\0'
после для)
в этой строке:
Nodo* insert = (Nodo*)malloc(sizeof(Nodo*));
Вы выделяете достаточно памяти только для указателя на Nodo, а не для всего Nodo. Вы хотите:
Nodo* insert = (Nodo*)malloc(sizeof(Nodo));
Кроме того, у вас может быть как минимум еще одна ошибка распределения:
insert->numBin = (char*)malloc(strlen(auxBin)*sizeof(char));
for(i=0 ; i<strlen(auxBin) ; i++)
insert->numBin[i] = auxBin[i];
Похоже, вы дублируете строку. Вам нужно выделить достаточно для строки плюс один, чтобы получить завершающий \ 0
. Вы можете упростить этот вызов стандартной библиотеки:
insert->numBin = strdup(auxBin);
РЕДАКТИРОВАТЬ: только что заметил, что вы работаете в Windows, поэтому strdup () может быть недоступен (это процедура POSIX), поэтому вы можете таким образом покрыть дублирование строк. Обратите внимание на +1 на длине терминатора:
insert->numBin = (char *)malloc( strlen(auxBin)+1 );
strcpy( insert->numBin, auxBin );
Когда вы выделяете память для строки (char *), убедитесь, что она имеет длину strlen +1 для \ 0 в конце.
insert->numBin = (char*)malloc(strlen(auxBin)*sizeof(char));
должен быть
insert->numBin = (char*)malloc(strlen(auxBin) + 1);
Также нет необходимости говорить * sizeof (char), который равен 1.
И еще Джон прав насчет того, как вы распределяете структуру, это должно быть не sizeof указателя, а sizeof структура.
Одна из проблем заключается в этой строке:
Nodo* insert = (Nodo*)malloc(sizeof(Nodo*));
она должна быть
Nodo* insert = (Nodo*)malloc(sizeof(Nodo));
(Практическое правило: у вас должно быть на один символ меньше * в sizeof ())
Вам нужно выделить место для структуры узла, НЕ пространство для указателя на структуру узла (которое, кстати, будет 4 байта в 32-битных системах)
Аналогичная проблема существует с нераспределением достаточно места для строки (массив символов); не забудьте пробел для завершающего нуля '\ 0'