2

我一直在用指针进行一些测试,并遇到了以下两种情况。谁能向我解释发生了什么?

void t ();
void wrong_t ();

void t () {
        int i;
        for (i=0;i<1;i++) {
                int *p;
                int a = 54;
                p = &a;
                printf("%d\n", *p);
        }
}

void wrong_t() {
        int i;
        for (i=0;i<1;i++) {
                int *p;
                *p = 54;
                printf("%d\n", *p);
        }
}

考虑以下两个版本的 main:

int main () {
        t();
        wrong_t();
}

打印:54\n54\n,如预期的那样

int main () {
        wrong_t();
}

产量:分段错误:11

我认为问题出在“wrong_t()”中的“int *p”是一个“坏指针”,因为它没有正确初始化(cfr.:cslibrary.stanford.edu/102/PointersAndMemory.pdf,第 8 页)。但是我不明白为什么在某些情况下会出现这样的问题(例如:如果我在 wrong_t() 之前调用 t() 或者如果我删除了 wrong_t() 中代码周围的 for 循环,则不会发生这种问题)。

4

3 回答 3

4

因为取消引用未初始化的指针(正如您正确猜测的那样)会调用未定义的行为。什么事情都可能发生。

如果您想了解您正在观察的精确行为,那么唯一的方法是查看编译器生成的汇编代码。但这通常不是很有成效。

于 2013-02-18T23:56:03.917 回答
3

What happens is almost certainly:

In both t and wrong_t, the definition int *p allocates space for p on the stack. When you call only wrong_t, this space contains data left over from previous activity (e.g., from the code that sets up the environment before main is called). It happens to be some value that is not valid as a pointer, so using it to access memory causes a segment fault.

When you call t, t initializes this space for p to contain a pointer to a. When you call wrong_t after this, wrong_t fails to initialize the space for p, but it already contains the pointer to a from when t executed, so using it to access memory results in accessing a.

This is obviously not behavior you may rely on. You may find that compiling with optimization turned on (e.g., -O3 with GCC) alters the behavior.

于 2013-02-19T00:02:44.313 回答
1

wrong_t功能上,这种说法*p = 54;很有趣。您正在尝试将值存储到p尚未为其分配内存的指针中,因此出现错误。

于 2013-02-18T23:57:47.623 回答