全局变量的危害

今日饱受一个全局变量的危害,导致多个项目出现问题,揪其根本原因是,全局变量的危害导致的。这里转载一篇关于全局变量危害的代码:
工作也有些年头了,从一位技术新人成长到现在自诩小牛级别的人物,少不了要自己寻找资料阅读。论坛上、书店里、杂志上......要嘛是些菜鸟浅薄的自炫处女贴,要嘛是高屋建瓴云里来雾里去的概念文,好不容易遇到个实践型高手写的文章,却在渐入佳境之际嘎然而止。本是隔靴搔痒,看完后心中更是郁结不已。也罢,今日且强装回大牛,献丑谈一谈嵌入式C编程中全局变量问题。
嵌入式特别是单片机os-less的程序,最易范的错误是全局变量满天飞。这个现象在早期汇编转型过来的程序员以及初学者中常见,这帮家伙几乎把全局变量当作函数形参来用。在.h文档里面定义许多杂乱的结构体,extern一堆令人头皮发麻的全局变量,然后再这个模块里边赋值123,那个模块里边判断123分支决定做什么。每当看到这种程序,我总要戚眉变脸而后拍桌怒喝。没错,就是怒喝。我不否认全局变量的重要性,但我认为要十分谨慎地使用它,滥用全局变量会引申带来其它更为严重的结构性系统问题。

诸位看官,且听我细细道来。

1. 它会造成不必要的常量频繁使用,特别当这个常量没有用宏定义“正名”时,代码阅读起来将万分吃力。

2. 它会导致软件分层的不合理,全局变量相当于一条快捷通道,它容易使程序员模糊了“设备层”和“应用层”之间的边界。写出来的底层程序容易自作多情地关注起上层的应用。这在软件系统的构建初期的确效率很高,功能调试进度一日千里,但到了后期往往bug一堆,处处“补丁”,雷区遍布。说是度日如年举步维艰也不为过。

3. 由于软件的分层不合理,到了后期维护,哪怕仅是增加修改删除小功能,往往要从上到下掘地三尺地修改,涉及大多数模块,而原有的代码注释却忘了更新修改,这个时候,交给后来维护者的系统会越来越像一个“泥潭”,注释的唯一作用只是使泥潭上方再加一些迷烟瘴气。

4. 全局变量大量使用,少不了有些变量流连忘返于中断与主回圈程序之间。这个时候如果处理不当,系统的bug就是随机出现的,无规律的,这时候初步显示出病入膏肓的特征来了,没有大牛来力挽狂澜,注定慢性死亡。

无需多言,您已经成功得到一个畸形的系统,它处于一个神秘的稳定状态!你看着这台机器,机器也看着你,相对无言,心中发毛。你不确定它什么时候会崩溃,也不晓得下一次投诉什么时候道理。

然后,我告诉大家现实层面的后果是什么。

1.“老人”气昂昂,因为系统离不开他,所有“雷区”只有他了然于心。当出现紧急的bug时,只有他能够搞定。你不但不能辞退他,还要给他加薪。
2. 新人见光死,但凡招聘来维护这个系统的,除了改出更多的bug外,基本上一个月内就走人,到了外面还宣扬这个公司的软件质量有够差够烂。
3.随着产品的后续升级,几个月没有接触这个系统的原创者会发现,很多雷区他本人也忘记了,于是每次的产品升级维护周期越来越长,因为修改一个功能会冒出很多bug,而按下一个bug,会弹出其他更多的bug。在这期间,又会产生更多的全局变量。终于有一天他告诉老板,不行啦不行啦,资源不够了,ram或者flash空间太小了,升级升级。
4. 客户投诉不断,售后也快崩溃了,业务员也不敢推荐此产品了,市场份额越来越小,公司形象越来越糟糕。

要问我的对策吗,只有两个原则:
1. 能不用全局变量尽量不用,我想除了系统状态和控制参数、通信处理和一些需要效率的模块,其他的基本可以靠合理的软件分层和编程技巧来解决。
2. 如果不可避免需要用到,那能藏多深就藏多深。
1)如果只有某.c文件用,就static到该文件中,顺便把结构体定义也收进来;
2)如果只有一个函数用,那就static到函数里面去;
3)如果非要开放出去让人读取,那就用函数return出去,这样就是只读属性了;
4)如果非要遭人蹂躏赋值,好吧,我开放函数接口让你传参赋值;5)实在非要extern**我,我还可以严格控制包含我.h档的对象,而不是放到公共的includes.h中被人围观,丢人现眼。
如此,你可明白我对全局变量的感悟有多深刻。悲催的我,已经把当年那些“老人”交给我维护的那些案子加班全部重新翻写了。你能明白吗,不要让人背后唾弃你哦。

2011-12-29 续篇
承蒙小编抬爱,推荐了本博文,感激之余心中惶恐,特地详细看了下回复。这个主题最早是在论坛发表的,我发现那里的回复还是比较热烈的,也很高兴能够听到不同的声音。对于一些网友提到的,如果大量使用局部变量也会容易造成栈溢出的问题,还提到程序模型的概念。言之有理。所以特地来补充一下意见:
1.全局变量是不可避免要用到的,每一个设备底层几乎都需要它来记录当前状态,控制时序,起承转合。但是尽量不要用来传递参数,这个很忌讳的。
2.尽量把变量的作用范围控制在使用它的模块里面,如果其他模块要访问,就开个读或写函数接口出来,严格控制访问范围。这一点,C++的private属性就是这么干的。这对将来程序的调试也很有好处。C语言之所以有++版本,很大原因就是为了控制它的灵活性,要说面向对象的思想,C语言早已有之,亦可实现。
3.当一个模块里面的全局变量超过3个(含)时,就用结构体包起来吧。要归0便一起归0,省得丢三落四的。
4.在函数里面开个静态的全局变量全局数组,是不占用栈空间的。只是有些编译器对于大块的全局数组,会放到和一般变量不同的地址区。若是在keil C51,因为是静态编译,栈爆掉了会报警,所以大可以尽情驰骋,注意交通规则就是了。
5.单片机的os-less系统中,只有栈没有堆的用法,那些默认对堆分配空间的“startup.s”,可以大胆的把堆空间干掉。
6.程序模型?如何分析抽象出来呢,从哪个角度进行模型构建呢?很愿意聆听网友的意见。本人一直以来都是从两个角度分析系统,事件--状态机迁移图 和 数据流图,前者分析控制流向,完善UI,后者可知晓系统数据的缘起缘灭。这些理论,院校的《软件工程》教材都有,大家不妨借鉴下。只不过那些理论,终究是起源于大型系统软件管理的,牛刀杀鸡,还是要裁剪一下的。

时间: 2024-10-26 05:48:25

全局变量的危害的相关文章

XSS危害——session劫持

在跨站脚本攻击XSS中简单介绍了XSS的原理及一个利用XSS盗取存在cookie中用户名和密码的小例子,有些同学看了后会说这有什么大不了的,哪里有人会明文往cookie里存用户名和密码.今天我们就介绍一种危害更大的XSS--session劫持. 神马是session 想明白session劫持及其危害,首先要搞清楚什么是session,熟悉http的同学知道,http是无状态的,也就是客户端向服务器请求完成后,会断开连接,下次同一个客户端再次访问服务器的时候,服务器会把它当作一个陌生的请求,不会知

XSS危害——session劫持(转载)

在跨站脚本攻击XSS中简单介绍了XSS的原理及一个利用XSS盗取存在cookie中用户名和密码的小例子,有些同学看了后会说这有什么大不了的,哪里有人会明文往cookie里存用户名和密码.今天我们就介绍一种危害更大的XSS--session劫持. 神马是session 想明白session劫持及其危害,首先要搞清楚什么是session,熟悉http的同学知道,http是无状态的,也就是客户端向服务器请求完成后,会断开连接,下次同一个客户端再次访问服务器的时候,服务器会把它当作一个陌生的请求,不会知

Python之路18-函数作用域、全局变量、局部变量

#全局变量 school = 'lianhedaxue' def test(name):     #强制修改全局变量     global school     school = 'haha'     print ('before change',name,school)     name = 'Jack'   #这个函数就是这个变量的作用域     print ('after change',name) name = 'Tom' test(name) print (name) print (s

全局变量导致所有命令都执行不了。

在配置MySQL时,做了个全局变量,少打了个"$"符号,导致所有命令都执行不了. 一开始我一直琢磨不出来为什么所有命令都执行不了. 如图: 要加个"$" 请用,命令全路径编辑/etc/profile: 输入: /usr/bin/vim /etc/profile 注意vim后有空格 然后将原来修改的内容删除 重新启动.shutdown -r now 或者reboot

C语言之全局变量和局部变量

全局变量和局部变量的简介(tips:很重要 牢记) 全局变量:就是定义在函数外的变量 全局变量可以在任意函数中使用 生命周期:程序一启动就开辟空间,直到程序退出才回收 全局变量不允许同名 局部变量:就是定义在函数内的变量 局部变量只能在它声明的位置开始到它所在的代码块结束 生命周期:它所在的代码块结束就回收 不同的作用域里,局部变量可以同名 tips:代码例子如下 #include <stdio.h> int globeNum = 10;   //全局变量 void test1(){ prin

线程间通信 1全局变量2当前主对话框指针3发消息方式4 AfxBeginThread的返回值(为CWinThread类型的指针)5AfxGetApp

①.最常用的方式:全局变量或者多个线程都能看到的一个东东 1.全局变量方式: int g_Num = 100; UINT __cdecl ThreadWriteProc(LPVOID lpParameter) { while(TRUE) { ++g_Num; Sleep(50); } return 100; } UINT __cdecl ThreadReadProc(LPVOID lpParameter) { CString strTipMsg; while(TRUE) { strTipMsg.

c语言全局变量和局部变量问题汇总

1.局部变量是否能和全局变量重名? 答:能,局部会屏蔽全局.要用全局变量,须要使用"::" 局部变量能够与全局变量同名,在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量.对于有些编译器而言,在同一个函数内能够定义多个同名的局部变量,比方在两个循环体内都定义一个同名的局部变量,而那个局部变量的作用域就在那个循环体内. 2.怎样引用一个已经定义过的全局变量? 答:extern 能够用引用头文件的方式,也能够用externkeyword,假设用引用头文件方式来引用某个在头文件

Objctive-C 全局变量

一,全局变量 1,在m文件中的所有方法,类定义和函数定义之外 例:Square.m中定义一个全局变量 , 在main.m中引用 Square.m代码如下: // //  Square.m //  Square // //  Created by Apple on 2017/9/9. //  Copyright  2017年 Apple. All rights reserved. // #import "Square.h" int global_val = 20;//定义一个全局变量 @

曝二手烟危害惊人数据:三亿人吞云吐雾,七亿人身处危险|秦皇岛威曼斯健康指南

内容来源:威曼斯环保(微信号:vmaxhb) 如果你是烟民,那么恭喜你,你不仅在害自己,也在害别人.吸烟的危害数据你真的知道吗?二手烟会有多大影响你知道吗? 在我国,吸烟人数超过了3亿,7.4亿非吸烟人群受二手烟的危害:每年130多万人死于吸烟导致的相关疾病,10万人死于二手烟所致危害.你认为吸烟是个人爱好,别人无权干涉?但那些不吸烟的人同样有拒绝二手烟的权利. 20个问答告诉你烟草危害的真相,最后知道真相的我眼泪掉下来!