Потеря данных в двусвязном списке строк

Рейтинг: -1Ответов: 1Опубликовано: 15.07.2023

У меня имеются две следующие структуры:

typedef struct _ListEntry {
    struct _ListEntry *next;
    struct _ListEntry *prev;
} ListEntry;
typedef struct _StringListEntry {
    char* value;
    ListEntry listEntry;
} StringListEntry;

Имеются такие макросы:

#define OFFSET_OF(TypeName, entryName)  \
    (char*)&((TypeName*)0)->entryName

#define GET_CONTENT_RECORD(TypeName, entryName, addr)    \
    ((TypeName*)((char*)addr - OFFSET_OF(TypeName, entryName)))

И код, который заполняет список случайными строками:

/string_list.c

StringListEntry* CreateAndInitNewStringListEntry(char* str) {
    StringListEntry* entry = (StringListEntry*)malloc(sizeof(StringListEntry));
    ListEntry* lst = (ListEntry*)malloc(sizeof(ListEntry));

    if (entry == NULL || lst == NULL) return NULL;

    entry->value = str;

    InitList(lst);
    entry->listEntry = *lst;

    return entry;
}
void AddStringTailStringList(StringListEntry* stringList, char* str) {
    ListEntry* head = &(stringList->listEntry);
    ListEntry* next = (ListEntry*)malloc(sizeof(ListEntry));
    
    InsertTailList(head, next);

    StringListEntry* newEntry = (StringListEntry*)malloc(sizeof(StringListEntry));
    newEntry->listEntry = *next;
    newEntry->value = str;

    return;
}
void GenerateRandomStringList(StringListEntry** stringList, unsigned int size) {
    srand(time(NULL));
    char* str;
    int count = 0, len;
    StringListEntry* stringListTmp = NULL;

    while (count < size) {
        len = rand() % MAX_STRING_SIZE + 1;
        str = (char*)malloc(sizeof(char) * (len + 1));
        for (int index = 0; index < len; index++) str[index] = CHARACTERS[rand() % COUNT_CHARACTERS];
        str[len] = '\0';

        if (count == 0) stringListTmp = CreateAndInitNewStringListEntry(str);
        else AddStringTailStringList(stringListTmp, str);

        count++;
    }

    *stringList = stringListTmp;
}

/list.c

void InitList(ListEntry* head) {
    head->prev = NULL;
    head->next = NULL;
    return;
}
void InsertTailList(ListEntry* head, ListEntry* newEntry) {
    if (head == NULL || newEntry == NULL) return;
    
    if (head->next == NULL) {
        head->next = newEntry;
        newEntry->next = NULL;
        newEntry->prev = head;
        return;
    }
    ListEntry* tmp = head->next;
    while (tmp->next != NULL) tmp = tmp->next;

    newEntry->prev = tmp;
    newEntry->next = NULL;
    tmp->next = newEntry;
    return;
}

Когда я пытаюсь вывести строки, то выводится только первая строка, у последующих "Ошибка при чтении символов строки", хотя по ListEntry движение происходит нормально. При отладке так же видно, что строки записываются корректно и добавление ListEntry в конец отрабатывает как надо. Подскажите, в чем может быть проблема?

void PrintStringList(StringListEntry* stringList) {
    StringListEntry* l;
    ListEntry* currentEntry = &(stringList->listEntry);
    while (currentEntry != NULL) {
        l = GET_CONTENT_RECORD(StringListEntry, listEntry, currentEntry);
        printf_s("%s\n", l->value);
        currentEntry = GetNextEntry(currentEntry);
    }
}

Ответы

▲ 0Принят

В итоге код для добавления в хвост списка должен выглядеть вот так:

void AddStringTailStringList(StringListEntry* stringList, char* str) {
    ListEntry* head = &(stringList->listEntry);
    
    StringListEntry* newEntry = (StringListEntry*)malloc(sizeof(StringListEntry));
    InsertTailList(head, &newEntry->listEntry);

    newEntry->value = str;
    return;
}

Из-за того, что память выделялась на next, и полю структуры присваивался указатель на него, GET_CONTENT_RECORD работал некорректно.