错误:“访问不在地址的映射区域内”(Valgrind)

时间:2018-11-10 16:49:34

标签: c valgrind

我与valgrind进行了一次探查,给我一个错误,指出“访问不在地址0x8的映射区域内”。然后说“在0x400606:append_linked_list(testing2.c:64)到0x400563:main(testing2.c:32)”。第64行是list->tail->next = newNode;,第32行只是调用append_linked_list(list, (void *) argv[i]);中第64行的函数。当我运行程序时,我只是将其作为“ ./testing这是一个相当短的测试字符串”来运行。有谁知道为什么valgrind给我这个错误?

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

typedef struct Node
{
    void *data;
    struct Node *next;
    struct Node *prev;
} Node;

typedef struct LinkedList
{
    Node *head;
    Node *tail;
} LinkedList;

Node *initialise_node(void);
LinkedList *initialise_linked_list(void);
Node *append_linked_list(LinkedList *list, void *data);

int main(int argc, char **argv)
{
    LinkedList *list;
    int i;

    list = initialise_linked_list();


    for(i = 1; i < argc; i++) 
    {
        append_linked_list(list, (void *) argv[i]);
    }
    return 0;
}

Node *initialise_node(void)
{
    Node *node;

    node = (Node *) malloc(sizeof(Node));

    return node;
}


LinkedList *initialise_linked_list(void)
{
    LinkedList *list;

    list = (LinkedList *) malloc(sizeof(LinkedList));
    list->head = NULL;
    list->tail = NULL;

    return list;
}

Node *append_linked_list(LinkedList *list, void *data)
{
    Node *newNode = initialise_node();

    newNode->data = data;
    newNode->prev = list->tail;
    list->tail->next = newNode;    
    newNode->next = NULL;

    return newNode;

}

2 个答案:

答案 0 :(得分:0)

  

“访问不在地址0x8的映射区域内”。然后说“在0x400606:append_linked_list(testing2.c:64)到0x400563:main(testing2.c:32)”。第64行是list->tail->next = newNode; [在函数append_linked_list中]

在列表为空的情况下,您的append_linked_list()函数会损坏,尤其是如Valgrind所说,由Valgrind标识的行将执行无效的内存访问。对您而言,这不是很明显,但是您仍然可以通过在调试器中研究程序的行为来自己发现它。

具体来说,当列表为空时,其list->tail指针为NULL,但是在这种情况下,程序尝试分配给list->tail->next。这是无效的。而且,您永远都无法为list->head分配非空值,这将在以后尝试遍历列表时给您带来麻烦。

最简单的方法是在列表为空时为所需的行为编写一个特殊情况:

if (list->tail) {
    list->tail->next = newNode;
} else {
    // Special case: empty list
    list->head = list->tail = newNode;
}

有些替代方法可以通过使数据结构稍微复杂一些来避免这种特殊情况的需要,但这将是一个不同答案的主题。

答案 1 :(得分:0)

Access not within mapped region at address 0x8

(按预期)意味着您访问的地址不在映射段中,地址为0x8。这通常意味着您访问的是NULL的结构指针。

在您使用调试信息重新编译时(例如,flas -ggdb

您得到:

==7797== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==7797==  Access not within mapped region at address 0x8
==7797==    at 0x4005CF: append_linked_list (delme.c:66)
==7797==    by 0x40052C: main (delme.c:33)

直接给出导致错误的行,如(在注释中指出):

list->tail->next = newNode;

0x8值来自以下事实:next是结构节点内的8个字节,因此&((Node *)NULL)->next是0x8