Glibc损坏的双链表

时间:2013-11-21 07:30:01

标签: c struct glibc realloc

我有一个程序可以读取文本文件并将其分为章节和段落结构。

struct paragraph
{
   char** lines;
   int numLines;
};

struct chapter
{
   struct paragraph** paragraphs;
   int numParagraphs;
};

struct book
{
   struct chapter** chapters;
   int numChapters;
};

以下是有问题的代码段,特别是realloc()语句:

//int numChapters = -1;
//char**** book = (void*)0;
struct book* books = malloc(sizeof(struct book*));
books->chapters = malloc(sizeof(struct chapter));

books->numChapters = -1;

//char*** nextChapter;
struct chapter* nextChapter = malloc(sizeof(struct chapter));


while ( (nextChapter = readChapter(bookFile))->paragraphs[0] )
{
    if (++(books->numChapters) > 0)
    {
        books = realloc(books, sizeof(struct chapter*)*books->numChapters);
        books->chapters[books->numChapters - 1] = nextChapter;

    }
}
books = realloc(books, sizeof(struct chapter*)*books->numChapters);
books->chapters[books->numChapters] = (void*)0;

return books;

此代码段中调用的函数应该可以正常工作,至少我是依赖于这个事实。这是一个记忆管理不善的问题。谢谢你的建议!

我应该提一下,它会通读前几章,然后就会出错。

1 个答案:

答案 0 :(得分:1)

也许你不需要在每个结构中使用两次指针?你有章节的数组,段落 - 不需要使用两次指针。

提供的代码更有可能使用数组,而不是列表。因此,如果您正在尝试使用列表 - 我在答案结束时提到了它们。否则,修复它以使用数组更简单,这是第一个问题:

if (++(books->numChapters) > 0)
{
    /* here books are reallocated */
    books = realloc(books, sizeof(struct chapter*)*books->numChapters);
    /* but here chapters which had not been reallocated are acessed */
    books->chapters[books->numChapters - 1] = nextChapter;

}

如果您有新章节,那么为什么需要重新分配书籍?只需重新分配书籍 - >章节:

if (++(books->numChapters) > 0)
{
    books->chapters = realloc(books->chapters, sizeof(struct chapter*)*books->numChapters);
    books->chapters[books->numChapters - 1] = nextChapter;

}

最后同样的问题:

/* books are reallocated, size is bad - reallocated to size of numChapters * (pointer size) */
books = realloc(books, sizeof(struct chapter*)*books->numChapters);
/* perhaps access to non-allocated memory here */
books->chapters[books->numChapters] = (void*)0;

应该是:

books->chapters = realloc(books->chapters, sizeof(struct chapter)*books->numChapters);
// books->chapters[books->numChapters] = (void*)0;

不需要为最后一个元素分配NULL,因为章节的大小为numChapters,访问元素numChapters导致访问非分配的内存,崩溃。

上面的所有代码都使用了数组的概念,而不是链接列表。

要将其切换到链接列表,必须使用以下结构:

struct paragraph
{
   struct paragraph *next; // <<-- this field is used to build
                           //      linked list of paragraphs
   char* lines;
   int numLines;
};

struct chapter
{
   struct chapter *next; // <<-- this field is used to build 
                         //      linked list of chapters
   struct paragraph* paragraphs;
   int numParagraphs;
};

struct book
{
   struct chapter* chapters;
   int numChapters;
};

当然,需要适当的分配和“下一个”指针的分配。