2015-05-30 58 views
-1

6.5版本(圣地亚哥) 用gcc版本4.4.7以及 红帽企业Linux服务器版本5.8(Tikanga) 用gcc版本4.1.2,我们可以写:指针在红帽企业Linux服务器,而内存分配提领

#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问题?

+9

因为您调用了未定义的行为。 –

+0

你似乎认为C中的任何内存错误都会导致段错误,这是一个巨大的误解。如果你是_lucky_,你可能会遇到段错误,但是具有未定义行为的代码可以做任何事情,包括出现正常工作或运行,但做一些奇怪或意外的事情。错误不会被编译器或操作系统捕获并转化为段错误,它是**您的责任,以避免错误,不依赖于它们被运行时注意到。 –

+3

参见http://c-faq.com/ansi/experiment.html有这样一个伟大的比喻:_“有人告诉我,在篮球中你不能控球并跑步,我得到了一个篮球并尝试过“# –

回答

2

您正在定义一个没有初始化它的指针。这意味着它有一个不确定的值,即。它指向内存中的一个随机点。写入这个位置不会导致段错误,因为段错误意味着您写入(或读取)的位置不是由您拥有。 但是,由于您在程序开始时运行了这个程序,指针仍然存在于堆栈中(请参见下文),所以仍然有可能通过某些隐藏的初始化代码指向程序中的某些变量。但如前所述,这是未定义的行为。它可能会导致段错误,它可能会在别处乱搞你的程序......没人知道。


通过我的意思是什么“仍然在栈上”是这样的:如果你的内存分配,比如说,一个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。 在这种情况下,a是有效的存储器(它是你的),但它是偶然访问的。所以它不会导致段错误。

+0

感谢你的描述,然而你的榜样没有奏效,实际上,segfalt出现 – alwaystudent

+0

好吧,那是未定义的为你行事; )。它可能工作,它可能不会 –

+0

好的,我有一些玩耍,事实证明,如果你将两个块转换成函数,它确实有效(对我来说)。我会更新代码。 –

相关问题