简体   繁体   English

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

[英]C Pointer Assignment: wrong address and segmentation fault

I'm having a really weird problem here, hope someone can help me. 我这里有一个很奇怪的问题,希望有人可以帮助我。 That's the code. 那就是代码。

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

Usually everything runs smoothly, but in some random cases I get a Segmentation Fault. 通常情况下,一切都运行顺利,但是在某些随机情况下,我会遇到细分错误。 I debuged with GDB. 我用GDB调试过。 Normaly the address of both list and node are 0x80d4000, but when the Segfault occurs, the address of node = 0x400. 通常,列表和节点的地址均为0x80d4000,但发生段故障时,节点的地址= 0x400。 (list is still 0x80d4000). (列表仍为0x80d4000)。
I really don't see where this could possibly go wrong, any ideas? 我真的不知道这可能会出错,有什么想法吗?

This is not enough code to be sure, but I suspect that somewhere, you pass a copy of an address (a pointer) and make modifications on the COPY (like a malloc); 这还不足以确保代码的正确性,但是我怀疑在某个地方,您传递了地址的副本(指针)并在COPY上进行了修改(如malloc); instead of passing the address of this address (pointer on a pointer), so you actually modify the pointer and not one of its copies. 而不是传递该地址的地址(指针上的指针),因此您实际上是在修改指针,而不是其副本之一。

An example to illustrate what I'm talking about: 一个例子来说明我在说什么:

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;
}

So here is what's happening: 所以这是正在发生的事情:

  1. You create a new char pointer set to NULL (better if you want to realloc, for instance). 创建一个新的char指针,将其设置为NULL(例如,如果要重新分配,则更好)。
  2. You pass its value (NULL) to dostuff . 您将其值(NULL)传递给dostuff The function makes a copy of this value (with a char* type), and modify this copy. 该函数复制此值(具有char *类型),然后修改此副本。
  3. printf accesses mystr for printing, and while trying to read from NULL[0] (0), will segfault. printf访问mystr进行打印,并尝试从NULL [0](0)读取时,将出现段错误。

The rest of the main isn't executed, of course. 当然,其余的main不会执行。

Here is why someone can fall into that pit: Usually, when you use some pointer with a function doing some modification on it, you modify its content , and not its address. 这就是为什么有人会陷入困境的原因:通常,当您对某个函数使用指针并对其进行了一些修改时,您将修改其内容 ,而不是其地址。 When you modify its address, you almost always (excepted in cases like this one) have the function modifying it to return its new address. 修改其地址时,几乎总是(在这种情况下除外)具有修改该地址以返回其新地址的功能。 Like in address = malloc(size) . 就像在address = malloc(size)

In the other hand, if you want to set a POINTER (and not is content obviously), you will need to pass a copy of its address to the function. 另一方面,如果要设置一个POINTER(显然不满足),则需要将其地址的副本传递给函数。 Here is the working version of the code above: 这是上面代码的工作版本:

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;
}

So remember: when in doubt, return the pointer and get the address of the other variables ( strlength here). 因此请记住:如有疑问,请返回指针并获取其他变量的地址(此处为strlength )。 If not possible, be very caucious about the actual type of the data you're manipulating, and double check your addresses after modification. 如果可能,请非常小心要处理的数据的实际类型,并在修改后仔细检查您的地址。

I hope it helps. 希望对您有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM