【问题标题】:C - Heap Corruption DetectedC - 检测到堆损坏
【发布时间】:2018-03-26 03:35:53
【问题描述】:

我从教授那里得到了使用指针创建一个列表的任务。当我尝试释放内存时,我在所有函数中都遇到了free() 的问题。我不断收到一条消息:

“检测到堆损坏:在 0x00D58CE0 的正常块 (#83) 之后。 CRT 检测到应用程序在堆缓冲区结束后写入内存。”

我不知道如何解决它。我尝试了不同的东西,但到目前为止没有任何效果。我也不确定在哪里可以找到它。我知道我的程序还没有得到适当的保护,但它不会影响问题。我试图先消除它,然后再进一步使用它。另外,您对在 Visual Studio 中检测程序的内存泄漏有什么建议吗?这是我的函数,完整的源代码在下面的链接中:

Full Source Code

struct ListElement
{
    int value;
    struct element *next;
};

typedef struct ListElement List;
typedef List *ListEl;

void ViewListBackwards(ListEl *list_el)
{
    ListEl current_element = *list_el;
    int size = 0;
    int i = 0;
    int *reversed_array;
    while (current_element->next != NULL)
    {
        size++;
        current_element = current_element->next;
    }
    current_element = *list_el;
    reversed_array = (int*)malloc(size * sizeof(*reversed_array));
    for (i = size; i >= 0; i--)
    {
        reversed_array[i] = current_element->value;
        current_element = current_element->next;
    }
    for (i = 0; i <= size; i++)
    {
        printf(" %d. %d\n", i + 1, reversed_array[i]);
    }
    free(reversed_array);
}

void RemoveFromListFront(ListEl *list_el)
{
    if (ListEmpty(list_el) == 0)
    {
        ListEl current_element = *list_el;
        *list_el = current_element->next;
        free(current_element);
    }
    else
    {
        printf("List is empty!\n");
    }
}

void RemoveFromListBack(ListEl *list_el)
{
    if (ListEmpty(list_el) == 0)
    {
        ListEl current_element = *list_el;
        ListEl last_element = *list_el;
        while (current_element->next != NULL)
        {
            last_element = current_element;
            current_element = current_element->next;
        }
        last_element->next = NULL;
        free(current_element);
    }
}

【问题讨论】:

  • 用于查找内存泄漏,Google _crtBreakAlloc。当您关闭程序时,如果您有内存泄漏,您应该在 Visual Studio 输出窗口中看到一个对象转储。然后您要做的是将 _crtBreakAlloc 添加到您的监视窗口,从对象转储中复制泄漏内存位置,并且在分配该位置时调试器将中断。还要注意VS 2013->2015版本,变量名略有不同。
  • ListEl new_element = malloc(sizeof(ListEl)); --> ListEl new_element = malloc(sizeof(*new_element));
  • 调试它,gdb 或在 Visual Studio 中(不知道如何,但它肯定是可能的)。找出导致崩溃的行
  • struct element *next; --> struct ListElement *next;先,建议你阅读编译器警告。

标签: c free heap-memory dynamic-arrays heap-corruption


【解决方案1】:

在以下代码中:

   reversed_array = (int*)malloc(size * sizeof(*reversed_array));
for (i = size; i >= 0; i--)
{
    reversed_array[i] = current_element->value;
    current_element = current_element->next;
}
for (i = 0; i <= size; i++)
{
    printf(" %d. %d\n", i + 1, reversed_array[i]);
}

您正在分配(相当于)一个int reversed_array[size] 数组,但随后继续写入reversed_array[size],即在分配的内存段末尾之后的sizeof(int)

您希望将 for 循环更改为:

for (i = size - 1; i >= 0; i--)

以便您编写的索引从 reversed_array[size - 1] 开始。

编辑:

顺便说一句,正如其他人在 cmets 中所建议的那样,不要强制转换 malloc()。这在 C 中是不需要的,因为 void * 可以分配给任何 对象指针 类型的变量,此外还可以隐藏代码中的错误,例如忘记包含 stdlib.h

而 FWIW,您不需要在 sizeof(*reversed_array) 周围加上括号,因为只有在将 sizeof 运算符应用于类型时才需要括号。

这主要是一种风格建议;许多人(包括我自己)更喜欢省略多余的括号并将该表达式写为sizeof *reversed_array,因为这清楚地表明sizeof是一个一元运算符而不是一个函数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-06
    • 2011-07-24
    • 1970-01-01
    • 2011-08-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多