【问题标题】:Seg fault when assigning pointer to null pointer [duplicate]将指针分配给空指针时出现段错误[重复]
【发布时间】:2018-07-20 04:04:04
【问题描述】:

我可能遗漏了一些关于指针和内存管理的非常重要的东西。 我正在建立一个双向链表。我有一个struct Node

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

nodep 是指向此类节点的指针的 typedef:

typedef struct Node * nodep;

现在我写了一个insertAt() 函数,它接受一个nodep lst,它基本上是一个指向列表中第一个元素的指针,或者NULL 表示空列表,一个int pos,它的位置插入元素和avoid* data,这是Node的payload。这是我的代码的摘录,我收到错误:

nodep insertAt(nodep lst, int pos, void *data){

    nodep new = malloc(sizeof(struct Node));
    [...]


    new -> data = data;
    assert(new != NULL);
    printf("memory allocated!\n");

    /* insert at last position */
    if(pos == -1) {
        [...]

    /* insert at first position */
    } else if (pos == 0) {
        if(lst == NULL) {
            new -> next = lst;
            lst = new;
        } else {
            [...]
        }

    /* insert at pos */
    } else {        
        [...]
    }

    return new;
}

这就是我在main() 函数中调用insertAt() 的方式:

int i;
nodep lst = NULL;

insertAt(lst, 0, "test");

当我用 valgrind 运行我的程序时,我得到一个

访问不在地址 0x10 的映射区域内

对于这行代码:

lst = new;

我想要做的是让nodep lst 指向nodep new,这就是列表的第一个元素。我真的不明白,为什么我会遇到这个错误。

提前感谢您的帮助。

干杯尼克

【问题讨论】:

  • 最好创建一个Minimal, Complete, and Verifiable Example 向我们展示。
  • 使用new作为变量名真的不是一个好习惯,在很多语言中都太像关键字了。
  • 如果你 typedef 指针,它会使程序不可读。
  • 另外,你知道C 按值 传递它的参数,这意味着它们被复制吗?这意味着在您的insertAt 函数中,变量lst 是一个副本,并且修改该副本(例如分配给它)不会更改您传入的原始变量。您可能想要这样做关于在 C 中模拟通过引用传递的一些研究
  • 此外,assert 宏在典型的发布版本中被禁用。它作为一个健全性检查器的使用被大大夸大和过度使用,特别是因为它解决问题的方法是强制中止(崩溃)程序。或者在发布版本中什么都不做。

标签: c pointers segmentation-fault valgrind ansi-c


【解决方案1】:

如果要修改lst,则必须使用双指针。

为了简单起见,我将使用int

int i;
int* ptr = &i;

func(ptr);
func(int* p){

   p = ....; //this won't change ptr!
}

func(&ptr);
func(int** p){

   *p = ....; //this will change ptr!
}

如果是双指针和sizeof(int) = 4sizeof(int*) = 4

 ---------------       ---------------        ---------------
|0x4|0x5|0x6|0x7|     |0x0|0x1|0x2|0x3|      |   |   |   |   |
 ---------------       ---------------        ---------------
 0x8 0x9 0xA 0xB      0x4 0x5 0x6 0x7         0x0 0x1 0x2 0x3
 address of p         address of ptr           address of i

*p 会给你 i 的地址。这是ptr 指向的地址。这就是为什么你用双指针来改变“外部”指针。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-04-09
    • 2020-11-13
    • 2020-02-18
    • 1970-01-01
    • 1970-01-01
    • 2021-12-22
    • 1970-01-01
    • 2016-01-02
    相关资源
    最近更新 更多