在这两个例子中,内存中会发生什么?

时间:2013-07-26 04:40:44

标签: c pointers gcc out-of-memory

使用MinGW 4.6.2(4.7.x似乎不是sourceforge上的“最新版本”,所以安装了这个版本)

void test(int *in)
{
    *in = 0;
}
int main()
{
    int dat;
    test(dat);
    return dat;
}

你可能知道这会在c项目中发出警告。

dirpath\fileName.c|8|warning: passing argument 1 of 'test' makes pointer from integer without a cast [enabled by default]

c ++项目中有2个错误。

dirpath\fileName.cpp|8|error: invalid conversion from 'int' to 'int*' [-fpermissive]|

dirpath\fileName.cpp|1|error: initializing argument 1 of 'void test(int*)' [-fpermissive]|

我的问题是,在以下两个场景中究竟发生了什么(在内存中),假设-fpermissive已启用或编译为c程序。

  1. dat未初始化且程序继续进行(并且不会发生分段错误)。
  2. dat被初始化为42,程序继续进行(并且会出现seg-fault)。
  3. 为什么离开dat未初始化导致没有seg-fault(可能偶然?),而情况2导致seg-fault(可能试图将值分配给内存位置)?

    好奇心f代表-fpermissive代表的是什么? (似乎多余)

3 个答案:

答案 0 :(得分:3)

该程序按原样具有未定义的行为,因此尝试推理其行为毫无意义,但无论如何......

test()函数需要一个指向int的指针。该指针将被取消引用并用于设置它指向的int。但是,你没有向它传递一个指向int但是未初始化int的指针 - 所以它会尝试将该变量中的任何垃圾值解释为内存地址,然后访问它后面的对象 - 和繁荣。

如果您想正确调用该函数,则需要编写

test(&dat);

代替。

  

f在-fpermissive中代表什么,也许是旗帜?

不,据我所知,它代表“功能”。 (但在-fpermissive的情况下,我会说它代表“你的代码是 f ..如果你使用这个标志,那就是ked ...” )

答案 1 :(得分:2)

正如警告所说passing argument 1 of 'test' makes pointer from integer,你试图从一个传递整数值的地址中取一些东西。它可能是任何东西。

当你传递值42时,编译器被迫在地址42获取一些值,这个值不是为用户保留的,而你正在获得Segfault.By默认编译器正在分配一些值,后来这个值变为地址,不知何故,你很幸运,你没有得到Segment故障。

答案 2 :(得分:1)

默认情况下,在c中发生按值传递

void test(int *in)
{
   *in = 0;
}

test(dat); // passing value

这里你传递的是未初始化的数据。它将考虑垃圾值。因此,您试图将garabage值作为测试函数中的内存地址。这是未定义的行为。相反,你可以试试这个。

test(&data);

来到你的问题。

Q. dat is uninitialized and the program proceeds (and no segmentation fault occurs).
A. This is an undefined behaviour because your are passing a garbage value. If your
   garbage value is a proper memory address then it will not cause segmentation error.
   If it is not proper, it will cause segmentaion error. So it happend at runtime 
   dynamically and can give either segmentation fault or can run.  

Q. dat is initialized to 42, and the program proceeds (and does seg-fault)
A. Here you have initialized dat to 42. By default c works on pass by value definition.
   So you are passing 42 to test. test will consider 42 as a memory location, which 
   is not a proper memory location so it cause segmentation error.