代码在代码段中的模糊行为

时间:2014-05-21 09:20:45

标签: c++ pointers

我正在使用指针并尝试不同的东西。

所以我在这里制作了一般的打印功能

void print(const int &value)
{
     cout << "value = " << value << " & address = " << &value << endl;
}

现在,这是一个以某种方式运作的代码:

  int j = 9090;
  int* p;
  *p = j; //Please read further
  print(*p);

我知道* p = j是不合逻辑的,我应该做p =&amp; j或p = new int等......但为什么这样做呢? 输出是

value = 9090 & address = 0x28ff48

此外,如果我打印j,地址是0x28ff44。这意味着它为p自动分配了新的内存(因为它的地址是..48)

现在,如果我只在j&#39; s声明之前添加另一行:

int i = 80;
int j = 9090;
int* p;
*p = j; //Please read further
print(*p);

^程序崩溃。

但是,如果我在声明p之后添加这个我的行,程序就会运行。

int j = 9090;
int* p;
int i = 80;
*p = j;
print(*p);

我做错了吗?我在Dev C ++ IDE 4.9.9.2中使用GCC编译器。发生了什么事?

3 个答案:

答案 0 :(得分:4)

问题是解除引用未初始化的指针是 undefined

这意味着任何事情都可能发生 - 有时程序会崩溃,有时会产生奇怪的结果,有时候(如果你不幸)它似乎会起作用。

由于您的指针未初始化,您将在其恰好代表的任何随机位置访问内存 有时,这是一个有效的地址,程序将继续运行 有时,它是一个无效的地址,程序会崩溃。

答案 1 :(得分:1)

int* p;
*p = j;

这是C ++的正确语法。这意味着在地址是p的字段中,你输入j的值。崩溃的问题源于你不为p提供任何记忆的事实。当你说int * p时,它意味着你有int变量的指针。但是,您没有在内存中提供任何实际地址来存储int值。 p中有一些垃圾,但这个垃圾被程序认为是有效的地址,它试图在那里写出j的值。如果你很幸运并且没有使用这个地址,程序将会更进一步。否则会崩溃。要避免这种未定义的行为,您需要为p:

分配内存
int* p = new int;
*p = j;

答案 2 :(得分:1)

  

我知道* p = j是不合逻辑的

在这种情况下,它是未定义的行为。您正在取消引用未初始化的指针,因此它有效地指向未知(随机)位置。

  

这意味着它为p

自动分配了新内存

不,它没有。您看到的地址只是随机的,未定义的值,最终会出现在未初始化的指针中。

  

为什么这样做?

这是未定义行为的事情:它可能是巧合,例如,如果指针中的随机值碰巧指向某个有效的可写内存区域,那么您的代码将适用于该特定运行。还有一次,它可能会崩溃。还有一次,它可能会破坏你的堆或一些不相关的数据,并在一段时间之后导致看似无关的崩溃或错误。这只是在你的调试器前面长时间尖叫;)

底线:不要这样做 - 不惜一切代价避免使用UB。

  

然而,如果我在声明p之后添加这个我的行,程序就会运行。

我认为您观察到的行为(崩溃与不崩溃)与代码更改没有直接关系,但巧合。事实上,如果你多次运行“工作”版本,我肯定你会在一段时间后崩溃。