поврежден двусвязный список после использования fclose();

У меня проблема в моей программе. После использования функции fclose() я получил ошибку:

"* Ошибка в `./server': поврежденный двусвязный список: 0x000000000251a230 * Przerwane (zrzut pamięci)"

Если я удалю функцию fclose(), все будет в порядке. Это код моей функции:

FILE *fHandler;
struct udp_message **returnArray;
struct udp_message *message;
char *line = NULL;
uint32_t linesNum;
uint32_t i = 0;
size_t length; 
ssize_t read;

fHandler = fopen(filePath, "r");
if (fHandler == NULL) {
    perror("ERROR");
    return NULL;
}

returnArray = malloc(sizeof(struct udp_message *)*CONSOLE_BUFFER);
message = malloc(sizeof(struct udp_message));

while ((read = getline(&line, &length, fHandler)) != -1) {
    message = (struct udp_message *)line;
    if (message->messageTime < aboveTime) {
        continue;
    }

    returnArray[i] = malloc(sizeof(struct udp_message));
    memcpy(returnArray[i++], message, sizeof(struct udp_message));
}

memcpy(messageNum, &i, sizeof(i));
fclose(fHandler);

return returnArray;

person Daniel Hornik    schedule 01.01.2016    source источник


Ответы (3)


Смотрите эту часть вашего кода-

message = malloc(sizeof(struct udp_message));       /* <--- 1 */

while ((read = getline(&line, &length, fHandler)) != -1) {
   message = (struct udp_message *)line;            /*  <--- 2.  */
   if (message->messageTime < aboveTime) {
       continue;
   }

Вы выделяете память для message (см. пункт 1.), но затем в цикле while указываете на line (пункт 2.).

Таким образом, вы теряете ссылку на ранее выделенную память (и оба этих указателя указывают на одно и то же место в памяти), и, следовательно, если вы free их , это будет free одна и та же память вызывая двойное free одно и то же место в памяти.

Итак, если вы хотите сделать message точкой line, не выделяйте память для message.

person ameyCU    schedule 01.01.2016
comment
@DanielHornik Добро пожаловать :-) - person ameyCU; 01.01.2016
comment
Вы правы, но чтение udp-сообщения с getline по-прежнему несовместимо с остальной частью кода, и цикл не проверяет, становится ли i слишком большим. Скорее всего, код на самом деле не работает, он просто больше не падает. - person chqrlie; 01.01.2016
comment
@chqrlie Это правда, поскольку значение CONSOLE_BUFFER нам неизвестно, поэтому без проверки i это может привести к выходу за границы доступа, вызывающему неопределенное поведение. - person ameyCU; 02.01.2016

Может быть стоит проверить, что объект не является нулевым

if(fHandler != NULL)
    fclose(fHandler);
person Konstantin Kulakov    schedule 01.01.2016

Маловероятно, что вы сможете прочитать свои двоичные сообщения UDP с помощью getline. Есть шанс, что цикл while повторится более CONSOLE_BUFFER раз, и вы будете писать за пределами конца returnArray, повреждая внутренние структуры кучи. fclose() освобождает буфер, связанный с потоком, free аварийно завершает работу из-за повреждения кучи.

Кстати, memcpy(messageNum, &i, sizeof(i));, вероятно, неверно. Вы не разместили прототип функции, но вы должны установить количество сообщений, хранящихся в returnArray с *messageNum = i;, особенно если тип не uint32_t *.

person chqrlie    schedule 01.01.2016