没有内存分配的指针解除引用

时间:2015-05-30 11:05:42

标签: c linux gcc

红帽企业Linux服务器版本6.5(圣地亚哥)中的

 与gcc版本4.4.7以及  红帽企业Linux服务器版本5.8(Tikanga)  使用gcc 4.1.2版我们可以写:

#include <stdio.h>

int main( int argc, char *argv[] )
{
   char * A;
   char * B=A;
   *B='C';   //run without segfalut
   *++B='\0';
   puts(--B);//print 'C' as well
   return 0;
}

问题是为什么不出现segfalut问题?

1 个答案:

答案 0 :(得分:2)

您正在定义指针而不进行初始化。这意味着它具有一个未定义的值,即。它指向内存中的随机点。根据定义,写入此位置不会导致段错误,因为段错误意味着您将(或读取)写入(或读取)非您拥有的位置。 但是,既然你在程序的最开始运行它,那么仍然在你的堆栈上的指针(见下文)仍有可能通过一些隐藏的初始化代码指向程序中的某个变量。但如上所述,它是未定义的行为。它可能会引起一个段错误,它可能只是把你的程序搞砸到其他地方......没人知道。

我的意思是&#39;仍然在堆栈上&#39;是这样的:如果你为一个int分配内存,这是通过将它放在堆栈上来完成的。现在堆栈略高,你的变量位于顶部。 现在,如果你分配一个变量(一个指针也只是一个变量,但包含一个地址),然后解除分配它,然后分配另一个变量,第二个变量的初始值与第一个变量相同。 (这也是未定义的,所以不要认为它是真的)。 假设我们有代码:

    #include <stdio.h>
    char a= 'A';
    void one()
            {
                    char* p1 = &a;
                    printf("char is '%c', addr = 0x%x\n", *p1, p1);
            }
    void two()
            {
                    char* p2;
                    printf("char is '%c', addr = 0x%x\n", *p2, p2);
            }

    int main(int argc, char** argv){
            one();
            two();
    }

很有可能会打印char is 'A'两次。因为p2指向的恰好与p1相同,这是一个。 在这种情况下,a是有效的内存(它是你的),但它是偶然访问的。所以它不会导致段错误。