C指针分配:错误的地址和分段错误

时间:2012-06-15 15:33:45

标签: c pointers segmentation-fault fault memory-address

我在这里遇到一个非常奇怪的问题,希望有人可以帮助我。这就是代码。

Node *fct(Node *list)
{
  Node *node;
  node = list;
  ...
}

通常一切都运行顺利,但在一些随机的情况下我得到了分段错误。我与GDB合作。 Normaly列表和节点的地址都是0x80d4000,但是当发生Segfault时,node = 0x400的地址。 (列表仍为0x80d4000) 我真的没有看到这可能出错的地方,任何想法?

1 个答案:

答案 0 :(得分:1)

这个代码不足以确定,但我怀疑在某个地方,你传递一个地址(一个指针)的副本并对COPY进行修改(就像一个malloc);而不是传递这个地址的地址(指针上的指针),所以你实际上修改了指针,而不是其中一个副本。

举例说明我在说什么:

int dostuff(char* str)
{
    str = malloc(sizeof(char));
    str[0] = 0x42;
    return 1; // size of string.
}

int main(int argc, char** argv)
{
    char* mystr = NULL;
    unsigned int strlength = 0;
    strlength = dostuff(mystr);
    printf("%s\n", mystr);  // Segfaults here: mystr == NULL.
    free(mystr);
    return 0;
}

所以这就是发生的事情:

  1. 您创建一个设置为NULL的新指针(例如,如果您想重新分配,则更好)。
  2. 您将其值(NULL)传递给dostuff。该函数复制此值(使用char *类型),并修改此副本。
  3. printf访问mystr进行打印,在尝试从NULL [0](0)读取时,会发生段错误。
  4. 当然,main的其余部分未执行。

    这就是为什么有人可以陷入这个陷阱的原因:通常,当你使用某个带有函数的指针对它进行一些修改时,你修改它的内容,而不是它的地址。当你修改它的地址时,你几乎总是(除了像这样的情况除外)有修改它的函数来返回它的新地址。就像在address = malloc(size)中一样。

    另一方面,如果你想设置一个POINTER(而不是显然是内容),你需要将其地址的副本传递给该函数。以下是上述代码的工作版本:

    int dostuff(char** str)
    {
        (*str) = malloc(sizeof(char));
        (*str)[0] = 0x42;
        return 1; // size of string.
    }
    
    int main(int argc, char** argv)
    {
        char* mystr = NULL;
        unsigned int strlength = 0;
        strlength = dostuff(&mystr);
        printf("%s\n", mystr);  // Now works: mystr is allocated.
        free(mystr);
        return 0;
    }
    

    请记住:如果有疑问,请返回指针并获取其他变量的地址(strlength此处)。如果不可能,请对您正在操作的数据的实际类型非常小心,并在修改后仔细检查您的地址。

    我希望它有所帮助。