分类: C/C++
2017-05-05 11:17:36
原文地址:编写安全代码:不要在头文件中定义变量 作者:gfree_wind
==========================================================================================================================================================
今天这个主题很简单。但是这么一个初级问题,居然真正发生在我的周围。
前几天帮助同事检查一个问题。他这样描述该现象:他定义了一个全局变量,然后调用一个函数F修改了该全局变量,但是退出函数时该全局变量的值又被改了。我到他的调试环境中,先查看了一下现象。问题重现了。—— 我一直认为,所有能够重现的问题都不是问题。只要能够重现,就一定可以修正。
对于这一问题,我的第一反应是竞争引起的。于是我首先使用GDB的set scheduler-locking on,保证其它线程处于停止状态,避免竞争。又试了一次,问题还是存在。在函数退出的时候,打印了一下当时的值。然后退出,再次打印,发现其值变为了初始值。感觉确实有点奇怪。于是看了看他的代码,一看该全局变量定义在头文件中static int g_variable = 0。看到这里,尽管我不知道其它代码是怎么写的。我就想到了问题的原因。这里的全局变量g_variable肯定有两份。函数F和调用者一定在不同的文件中,它们都include了这个头文件。结果在函数F中修改了一个g_variable,而调用者中使用和查看的是另一个g_variable。解决方法是,去一个c文件中定义这个全局变量,然后到头文件中声明。
虽然我很快的解决了这个问题。但是我却想,这个问题真的是一个很初级的问题。而我这位同事已经是一名senior的开发人员了。为什么还会犯这种错误呢?这里我对事不对人。主要的原因还是对于编程的基础没有理解。头文件中不要定义全局变量,看似是一条死的规则。其实只要真正领会什么是头文件,头文件是如何include到.c源文件中的。这条规则根本不需要记忆,而是一种理解。这样会自然的就会写出正确的代码,而不会犯这样的错误。
说到这里,简单说一下头文件的知识。头文件的作用,主要是用于声明变量,函数等等,然后可以被多个源文件引用。其实我认为其根本目的,一是为了代码的整齐,更重要是为了消除重复的代码。因为多个源文件都要相同的声明,这时就可以用一行include 头文件来解决。而include,在预编译阶段,实际上是将头文件中所有的代码都插入到include的位置。真正理解了这个过程,肯定不会犯本文中的这个错误。