【问题标题】:C - Segfault when accessing member of non null pointer structC - 访问非空指针结构的成员时出现段错误
【发布时间】:2012-03-05 03:09:03
【问题描述】:

我用 C 语言制作了一个基本的 LinkedList,我可以创建、添加和开始工作。除了 get 在看似随机数量的 get 调用(第 96 次调用失败,列表中有 94 个元素)后会导致段错误外,访问当前节点上的 next 指针会导致段错误。

这一行导致了段错误while(cur->next != null && i < index) 我已经检查过,并且在段错误发生之前 cur 没有返回空内存地址。它还会在导致它崩溃的调用的第二个循环中崩溃(第二个 printf 仅输出 0)。 这是整个get函数

void *linkedList_get(LinkedList list, int index)
{
    Node *cur = list.head;
    int i = 0;
    if(index != 0)
    {
        while(cur->next != null && i < index)
        {
            cur = cur->next;
            printf("I %i\n", i);
            printf("%i\n", cur);
            i++;
        }
    }
    if(index == i)
        return cur->data;
    return null;
}

这是节点结构

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

如果需要的话,这是完整的代码http://pastebin.com/hpWA8tb8(注意这是我的第一个 C 程序,所以它可能有点草率而且我没有释放任何内存)

【问题讨论】:

  • 可能不是你的 bug 的来源,但你应该修改上面的函数,在取消引用 cur->next 之前检查以确保 list.head 不为 NULL。
  • 如果在调试器下运行这个程序,发生段错误时调用栈是什么样的?
  • 我正在使用带有 Mingw32 的 Code::Blocks 并且由于某种原因调试器拒绝工作,这使得调试我作为初学者 C 程序员引起的大量段错误非常难以调试哈哈。
  • 我从不关心 C++,但我主要是一名 Java 程序员,所以 OOP 是我的背景。为什么不用typedef呢?我知道的唯一区别是我必须做 struct structname varname 而不是 structname varname 这对我来说似乎更好。

标签: c memory struct segmentation-fault


【解决方案1】:

createEmptyNode 实际上并不返回n。这意味着链表中使用的节点指针实际上是伪造的(并且指向内存中的任何位置)。您的许多其他创建函数也是如此。

您应该在启用警告的情况下进行编译,这可能会发现这一点。 (例如,在 GCC 上使用 -Wall)。

一般来说,如果您在 C 程序中存在任何内存错误,那么在触发该错误后,您就无法完美地推断出它的行为。所以我不会声称修复它会使其工作。 ;-) 在节点中设置数据、分配指针而不是指针的内容时也会出现错误(为此,您应该使用 memmove 之类的东西,明确传递内容的大小)。

【讨论】:

  • 哇,我不敢相信我忘记了每个函数的返回值。但它仍然在同一点崩溃。
  • 你会推荐使用 valgrind 吗?
  • 我从未使用过 valgrind,尽管我已经在很多我应该使用的地方阅读过!我有时在 MSVC 中运行代码,它可以检测到一些内存错误(可能类似于 valgrind)。
  • 如果您在编译时启用所有警告,是否还有其他警告消息尚未解决?
  • 有 11 个警告,到目前为止我一直忽略它们,因为它们似乎没有影响任何东西,而且我真的不知道它们是什么意思。警告i.imgur.com/3bcrf.png 错误是因为我必须有一个编译错误才能显示出于某种原因的警告。
【解决方案2】:

Edmund 很可能找到了答案。但我也抓住了这个:

这是非常危险的错误,尤其是在 64 位操作系统上,并且编译时 sizeof 指针大于 sizeof(int)。

Node *n = malloc(sizeof(int) * 3);

应该是:

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

【讨论】:

    【解决方案3】:

    正如埃德蒙所说,这个程序可能有很多错误,

    我反对这部分:

    next->data = malloc(sizeof(data));
    next->data = data;
    

    它为 next->data 分配一些内存,然后立即擦除该指针,并放入不同的值。内存肯定泄露了,可能会导致其他后果。

    【讨论】:

    • 我还没有完全搞定手动内存管理,但我确实知道这样做没有意义,所以我删除了 malloc 调用。
    • data 也是 void * 类型——您应该将数据的大小从 getFilesInDir 等传递到 linkedList_add 中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-25
    相关资源
    最近更新 更多