运行时坏指针的行为

时间:2013-02-18 23:52:37

标签: c pointers

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

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循环,则不会发生这种情况。

3 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:3)

几乎可以肯定会发生什么:

twrong_t中,定义int *p在堆栈上为p分配空间。当您只调用wrong_t时,此空间包含以前活动遗留的数据(例如,来自在调用main之前设置环境的代码)。它恰好是一些无效的指针值,因此使用它来访问内存会导致段错误。

当您致电t时,t会为p初始化此空间,以包含指向a的指针。在此之后调用wrong_t时,wrong_t无法初始化p的空间,但它已经包含从a执行时t的指针,因此使用它访问内存导致访问a

这显然不是您可能依赖的行为。您可能会发现启用优化的编译(例如,-O3与GCC)会改变行为。

答案 2 :(得分:1)

wrong_t函数中,此语句*p = 54;很有意思。您正在尝试将值存储到指针p中,而您尚未分配内存,因此错误。