【问题标题】:How is it possible to have null defernce if null is checked before如果之前检查了 null,怎么可能有 null defernce
【发布时间】:2022-12-18 09:25:32
【问题描述】:

我有这个功能可以搜索跳过列表中的元素。我不明白address sanitaizer给出的错误:

==5461==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000010 (pc 0x555555555e28 bp 0x7fffffffdeb0 sp 0x7fffffffde90 T0)
==5461==The signal is caused by a READ memory access.
==5461==Hint: address points to the zero page.
    #0 0x555555555e28 in search_skip_list (/home/matteo/Scrivania/Algo/laboratorio-algoritmi-2021-2022-main/Esercizio 2/ex2/build/main+0x1e28)
    #1 0x5555555556fb in main (/home/matteo/Scrivania/Algo/laboratorio-algoritmi-2021-2022-main/Esercizio 2/ex2/build/main+0x16fb)
    #2 0x7ffff73c3d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #3 0x7ffff73c3e3f in __libc_start_main_impl ../csu/libc-start.c:392
    #4 0x5555555552e4 in _start (/home/matteo/Scrivania/Algo/laboratorio-algoritmi-2021-2022-main/Esercizio 2/ex2/build/main+0x12e4)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (/home/matteo/Scrivania/Algo/laboratorio-algoritmi-2021-2022-main/Esercizio 2/ex2/build/main+0x1e28) in search_skip_list
==5461==ABORTING
[Inferior 1 (process 5461) exited with code 01]

我的代码中没有发现分段错误。我是C新手,不知道如何正确使用gdb来查找问题。我把功能和结构初始化的方式放在这里,完整的代码太长,项目被文件占用。

void* search_skip_list(SkipList *list, void* item){
    if(list == NULL || item == NULL ) return NULL;

    Node *x = list->head;
    
    for (int i = list->max_level-1; i >= 0; i--)
    {   
        while (x->next[i]!=NULL && strcmp(item,x->next[i]->item) < 0)
        {
           x = x->next[i];
        }  
     }
    x = x->next[0];

    if(strcmp(item,x->item) == 0) return x->item;
    else{
        return "failure";
    } 
}
struct _SkipList {
    Node *head;
    unsigned int max_level;
    int (*compare)(void*, void*);
};
struct _Node {
    Node **next;
    unsigned int size;
    void *item;
};
SkipList* create_skip_list(){
    SkipList *list = malloc(sizeof(SkipList));
    list->max_level = 0;
    list->compare = NULL;
    list->head = create_head_node(NULL,MAX_HEIGHT);
    return list;
}
Node* create_head_node(void* item, int level){
    if(level <1) return NULL;
    Node *node = malloc(sizeof(Node));
    if(node == NULL){
        printf("error malloc node");
    }
    node->item = item;
    node->size = level;
    node->next = (Node**)malloc(level * sizeof(Node));
    for (int i = 0; i < node->size; i++)
        {
            node->next[i] = NULL;
        }
    if(node == NULL){
        printf("error malloc node->next");
    }
    return node;
}

我发现这可能是对 NULL 指针的尊重,但我不明白这怎么可能。但我认为这很奇怪,因为我首先检查是否有 NULL 值。还有其他问题可能会导致此错误吗?如何正确使用 GBD 找到问题所在的确切行?

我在函数之前使用断点运行 gdb,并且似乎在它第一次进入函数时停止,就好像第一个元素是 NULL 并且遵循 NULL 指针一样。

【问题讨论】:

  • 如果x-&gt;next[i]-&gt;item 为 NULL 怎么办?
  • - 或list-&gt;head
  • 我很确定这已经是错误的:Node *x = malloc(sizeof(Node)); x = list-&gt;head; 如果您立即覆盖指针,为什么要创建一个节点/分配内存。这至少是内存泄漏。那么在下面的代码中,list->head 当然可以是 null_ptr,也可以是 x,你刚刚分配给了这个指针。
  • ``节点x = malloc(sizeof(Node)); x = 列表-> 头部;是一个尝试,整数值与一个简单的节点一起工作x=列表->头
  • 该报告以“未知地址 0x000000000010 上的 SEGV”开头。 0x000000000010 很可能确实是该程序的无效地址,但很可能才不是对应一个空指针。它看起来像是对空指针执行一些算术的结果(它具有未定义的行为,但实际上不太可能产生段错误)。

标签: c segmentation-fault gdb


【解决方案1】:

为了防止内存访问错误,我建议你这样重写你的函数:

Node* create_head_node(void* item, int level){
    if(level <1)
        return NULL;

    Node *node = malloc(sizeof(Node));
    if(node == NULL){
        printf("error malloc node
");
        /* Returning here prevent the program from accessing non allocated
         * memory. */
        return NULL;
    }

    node->item = item;
    node->size = level;

    node->next = (Node**)malloc(level * sizeof(Node *));
    if (!node->next) {
        printf("error malloc node next
");
        free(node);
        return NULL;
    }

    for (int i = 0; i < level; i++)
    {
        node->next[i] = NULL;
    }

    return node;
}

【讨论】:

  • 我总是不鼓励在 C++ 中使用 goto 并且这段代码在此处的分配中仍然有错误的大小:node-&gt;next = (Node**)malloc(level * sizeof(Node));
猜你喜欢
  • 2013-07-14
  • 2010-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-07
  • 2010-12-27
  • 1970-01-01
  • 2010-10-09
相关资源
最近更新 更多