【问题标题】:Heap corruption in an intrusive data structure example侵入式数据结构示例中的堆损坏
【发布时间】:2017-11-13 16:05:42
【问题描述】:

这是一个双向链表,节点/链接携带存储在列表中所需的信息(侵入式):

dlist.h:

#ifndef DLIST_H
#define DLIST_H

//--------------------------------------------------------------------------

typedef struct Link
{
    struct Link* succ;
    struct Link* prev;
} Link;

//--------------------------------------------------------------------------

typedef struct List
{
    Link* first;
    Link* last;
} List;

//--------------------------------------------------------------------------

void init(List* lst)
{
    assert(lst);

    lst->first = 0;
    lst->last = 0;
}

//--------------------------------------------------------------------------

List* create()
{
    List* lst = (List*) malloc(sizeof(List*));

    init(lst);

    return lst;
}

//--------------------------------------------------------------------------

void push_back(List* lst, Link* l)
{
    assert(l);
    assert(lst);
    {
        Link* last = lst->last;

        if (last)
        {
            last->succ = l;
            l->prev = last;
        }
        else
        {
            lst->first = l;
            l->prev = 0;
        }

        lst->last = l;
        l->succ = 0;
    }
}

//--------------------------------------------------------------------------

void clear (List* lst)
{
    assert(lst);
    {
        Link* curr = lst->first;
        Link* next = 0;

        while (curr)
        {
            next = curr->succ;

            free(curr);

            curr = next;
        }

        lst->first = 0;
        lst->last = 0;
    }
}

//--------------------------------------------------------------------------

void destroy (List* lst)
{
    assert(lst);

    clear(lst);

    free(lst);
}

//--------------------------------------------------------------------------

typedef struct Name
{
    Link l;
    char* s;
} Name;

//--------------------------------------------------------------------------

Name* make_name(char* str)
{
    Name* n = (Name*) malloc(sizeof(Name*));
    n->s = str;

    return n;
}

//--------------------------------------------------------------------------

#endif

main.c:

#include <stdlib.h>     // malloc
#include <stdio.h>      // printf
#include <assert.h>     // assert


#ifdef __cplusplus  


#else  // compiling in C. 

int main ()
{
    List* lst = create();

    char* names[ ] = { "Giorikas", "Kostikas", "Foo", "Bar", "Gosho", "Pesho" };
    char* name;

    int i = 0;
    int size = 6;

    for (i; i < size; ++i)
    {
        push_back(lst, (Link*)(make_name(names[i])));

        name = ((Name*)(lst->last))->s;
        printf("Name: %s \n", name);
    }

    destroy(lst);

    getchar();

    return 0;
}

#endif

使用调试器,我打印了名称,在函数clear() 中,第一次尝试释放链接时,我收到两个警告,最后:

_CrtIsValidHeapPointer(pUserData)

注意:经过一番研究,我了解到:“您不会在重写时立即收到堆损坏,而是 在下一次堆检查时,这将在任何下一次内存分配/释放。”。因此,clear() 中发生的可能是触发错误的堆检查。

这个堆损坏发生在哪里?

【问题讨论】:

  • 完全不相关,但名称更有意义的是succ/pred 或next/prev,而不是succ/prev。
  • 与您的问题无关,但不要将函数定义(实现)放在头文件中。相反,只需将函数的声明放在头文件中,然后将定义放在单独的源文件中,然后使用该文件进行构建。
  • @BLUEPIXY 你是说演员吗?
  • @BLUEPIXY 我将Name理解为基类Link的“派生”类
  • @Someprogrammerdude 啊,我误解了Link 和Link*。我似乎没有足够的睡眠。对不起 Ziezi 和一些程序员老兄。

标签: c data-structures heap-memory


【解决方案1】:

你做了错误的分配。你需要分配 objects 而不是指针,所以:

List* lst = (List*) malloc(sizeof(List*));

应该是

List* lst = (List*) malloc(sizeof(List));

至少Name也是如此。您也可以移除演员表:

List* lst = malloc(sizeof(List));

-----编辑----

还有一个更好的习语是:

List* lst = malloc(sizeof(*lst));

【讨论】:

  • 感谢您指出问题和分配成语!
猜你喜欢
  • 2011-10-02
  • 1970-01-01
  • 2016-08-23
  • 1970-01-01
  • 2021-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多