关闭

没有躲过的坑--程序中的变量未初始化

标签: c++初始化
11825人阅读 评论(2) 收藏 举报
分类:

变量未初始化是C++编程中最为常见和易犯的错误之一。

但是对于全局变量,我们可以不进行初始化,这个变量会默认的用零进行初始化,但是这通常不是一个好的习惯。我们今天先不探讨全局变量还是静态全局变量。那么对于一个全部变量来说,初始化为零和不初始化(编译器替我们初始化为零)又有什么区别吗?

全局变量和局部变量初始化与不初始化的区别
即int x 和 int x=0的区别。

int x =0; 跟 int x; 的效果看起来是一样的。但其实这里面的差别很大,强烈建议大家所有的全局变量都要初始化,他们的主要差别如下:

编译器在编译的时候针对这两种情况会产生两种符号放在目标文件的符号表中,对于初始化的,叫强符号,未初始化的,叫弱符号。连接器在连接目标文件的时候,如果遇到两个重名符号,会有以下处理规
则:
1、如果有多个重名的强符号,则报错。
2、如果有一个强符号,多个弱符号,则以强符号为准。
3、如果没有强符号,但有多个重名的弱符号,则任选一个弱符号。

例:

#include "stdafx.h"
int i;
int main(int argc, char* argv[])
{
 printf(" i = %d\n",i);
 int j;
 printf(" j= %d\n",j);
 return 0;
}

在Debug版下,i输出是0,j输出是-858993460,也就是0xCCCCCCCC。
至于为什么是这个值,有网友给出这个解释。(设计成0xcccccccc是有特殊用意的……这个好像叫做Poison,未初始化的Pointer去取值的话会出错。肯定有人问为什么不弄成0x00000000,因为空指针是指针的有效状态,可能会误导人,而0xCCCCCCCC在Windows下永远不可能是一个指针的有效状态(不是NULL,不指向一个对象,不指向一堆对象紧接之后的区域),这就是在模拟野指针……)

值得注意的是,同样的代码在Release版下,这段代码中未被初始化的变量最后打印出来的可能都是0。也有强大的网友给出解释。(重点在于vc的一个功能:Catch release-build errors in debug build用/GZ编译开关打开。debug版这个开关是开的,release版是关的(为了效率)。这个开关说白了就是把所有动态局部变量初始化成0xcccccccc,把所有动态堆变量初始化成0xcdcdcdcd。很多新手会忘记初始化这些本来应该初始化的变量(尤其是new出来的变量),有时他们会假定这些变量应该是0,这样就可能出现在release版正常而debug版不正常的程序,因为release版至少局部变量的初始值很可能就是0,而有时他们又会假定或者期望这些变量不是0,这样就带了一个最难发现的bug)

上面的内容出自:
http://www.kingofcoders.com/viewNews.php?type=newsCpp&id=189&number=4836955386

================================================

在C++中,为变量所分配的内存空间并不是完全“干净的”,也不会在分配空间时自动做清零处理。其结果就是,一个未初始化的变量将包含某个值,但没办法准确地知道这个值是多少。此外,每次执行这个程序的时候,该变量的值可能都会发生改变。这就有可能产生间歇性发作的问题,是特别难以追踪的。看看如下的代码片段:

if (num_value)
{}
else
{}

如果num_value是未经初始化的变量,那么if语句的判断结果就无法确定,两个分支都可能会执行。在一般情况下,编译器会对未初始化的变量给予提示。下面的代码片段在大多数编译器上都会引发一个警告信息。

int foo()
{
    int number;
    return number;
}

但是,还有一些简单的例子则不会产生警告:

void increment(int &num_value)
{
    ++num_value;
}
int foo()
{
    int number;
    increment(number);
    return number;
}

以上的代码片段可能不会产生一个警告,因为编译器一般不会去跟踪查看函数increment()到底有没有对nValue赋值。

未初始化变量更常出现于类中,成员的初始化一般是通过构造函数的实现来完成的。

class Foo
{
private:
    int num_value_;
public:
    Foo();
    int GetValue() { return num_value_; }
};

Foo::Foo()
{

// Oops, 我们忘记初始化num_value_了
}

int main()
{
    Foo cFoo;
    if (cFoo.GetValue() > 0)

// do something
    else

// do something else
}

注意,num_value_从未初始化过。结果就是,GetValue()返回的是一个垃圾值,if语句的两个分支都有可能会执行。

==================================================
新手程序员通常在定义多个变量时会犯下面这种错误:

int nValue1, nValue2 = 5;

这里的本意是nValue1和nValue2都被初始化为5,但实际上只有nValue2被初始化了,nValue1从未被初始化过。

切记 无论什么变量,记得初始化!!!!

2
0
查看评论

关于C语言中的未初始化变量的值

我们在刚学C编程的时候经常碰到“烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫”,这是为什么呢? 先从上次某公司笔试说起,当时有一题是考到了关于变量初始化的问题。在主函数外面(全局)和里面(局部)个定义一个int类型数值。然后没有赋值,直接打印出来,问输出什么。那会只知道全局默认是0,局...
  • deqingguo
  • deqingguo
  • 2013-01-24 20:16
  • 10154

未初始化全局变量

未初始化全局变量   为下一篇介绍进程内存分布做准备,这一篇先来介绍一下未初始化全局变量:   未初始化全局变量,这名字就很直白,就是 C 程序中定义成全局作用域而又没有初始化的变量,我们知道这种变量在程序运行后是被自动初始化为 全0 的。编译器编译的时候会将这类变量收集起来集中放置到 .bs...
  • liuqiaoyu080512
  • liuqiaoyu080512
  • 2012-12-31 16:40
  • 5970

不初始化变量的后果

昨天终于尝到了滋味。 情况是这样的:当我写完程序,高高兴兴地测试了一遍,一切正常,很OK。这时候是Debug版本的。 然后切换到Release 时,出现了很不科学的情况。有时候正常,有时候不正常= = 坑爹啊。 于是问老大,遂回答可能是有的变量没初始化就用到了,因为Debug是帮你把没初始化的...
  • KIVET
  • KIVET
  • 2012-10-25 08:39
  • 240

分享一个 变量没有初始化 可能带来的问题

先看 code: static void do_ctors_aux(void) { /* SGX RTS does not support .ctors currently */ fp_t *p = NULL; uintptr_t init_array_ad...
  • guilanl
  • guilanl
  • 2017-02-22 11:54
  • 162

DSP2812调试:全局变量初始化不是指定的赋值结果

调试DSP2812的时候,定义了一些全局变量,刚刚下载进去,调试观察发现这些变量并非为初始化的值?     why??     难道是内存不够,溢出了??   正在解决...
  • zz603976046
  • zz603976046
  • 2015-01-29 22:10
  • 358

java中变量未初始化

java中的变量未初始化,会出现什么问题呢,如果是基本数据类型,则会有初始值,如果不是,则一般是null,以下为测试结果 public class Test { String str; int a; char b; short s; float f; long lo; double ...
  • lsx991947534
  • lsx991947534
  • 2015-05-22 18:53
  • 2398

建议对php变量进行初始化、用完后清空

我们知道, 在php中, 变量不需要提前定义, 想用就用即可。 从我写php代码的经验来看, 建议对php变量进行初始化、用完后清空, 能避免很多串扰问题。 踩过太多的坑了。 C/C++就不存在这个问题, 爽爽哒!
  • stpeace
  • stpeace
  • 2016-12-10 15:19
  • 4144

QT中变量不初始化时的值

在QT Creator中,若在Debug模式下,改变全局变量的初始值要在构建中清除项目,不然再次运行时此次改变不起作用 ,仍运行改变前的代码,结果不变,这极易造成代码调试过程出错,切记。同时,养成手动初始化所有变量的习惯
  • Hujun1994
  • Hujun1994
  • 2015-10-29 19:02
  • 519

Keil MDK下如何设置非零初始化变量

一些工控产品,当系统复位后(非上电复位),可能要求保持住复位前RAM中的数据,用来快速恢复现场,或者不至于因瞬间复位而重启现场设备。而keil mdk在默认情况下,任何形式的复位都会将RAM区的非初始化变量数据清零。如何设置非初始化数据变量不被零初始化,这是本篇文章所要探讨的。   ...
  • zhzht19861011
  • zhzht19861011
  • 2013-04-10 08:08
  • 13720

莫偷懒!成员变量一定要初始化!

莫偷懒!成员变量一定要初始化! 未初始化的bool成员变量在Debug下默认值为false,Test下默认true。一个bug查了一晚上,原因就是这个. 人物创建的场景在Debug下正常,在Test和Release下不正常,就是镜头不对。然后就盯着这个载入场景的配置文件的代码看,ini不用了...
  • luliyuan
  • luliyuan
  • 2014-04-22 14:35
  • 2387
    个人资料
    • 访问:4745674次
    • 积分:42216
    • 等级:
    • 排名:第96名
    • 原创:571篇
    • 转载:29篇
    • 译文:13篇
    • 评论:784条
    微信公众号
      我的微信公众号
      为你推荐最新的博文~更有惊喜等着你
    时光荏苒
      白驹过隙
    博客专栏
    文章分类
    百度统计
    Google Analytics