C语言全局变量那些事儿(2)
更新时间:2023-07-22 21:46:01 阅读量: 实用文档 文档下载
第三个例子
这个例子代码同上一个一致,只不过我们将foo.c做成一个静态链接库libfoo.a进行链接,这里只给出Makefile的改动。
test: main.o foo.o ar rcs libfoo.a foo.o gcc -static -o test main.o libfoo.a main.o: main.c foo.o: foo.c clean: rm -f *.o test
运行情况如下:
foo: (&b)=0x080ca008
sizeof(b)=8
b.a=2
b.b=4
main:0x08048250
parent: (&b)=0x080ca008
(&c)=0x080cc084
sizeof(b)=4
b=2
c=0
wait child...
child: sleep(1)
(&b):0x080ca008
(&c)=0x080cc084
sizeof(b)=4
set b=1
c=0
foo: (&b)=0x080ca008
sizeof(b)=8
b.a=1
b.b=4
main:0x08048250
parent: child over
(&b)=0x080ca008
(&c)=0x080cc084
sizeof(b)=4
b=2
c=0
从这个例子看不出有啥差别,只不过使用静态链接后,全局变量加载的地址有所改变,b和c的地址之间似乎相隔更远了些。不过这次编译器倒是给出了变量b的sizeof决议警告。
到此为止,有些人可能会对上面的例子嗤之以鼻,觉得这不过是列举了C语言的某些特性而已,算不上黑。有些人认为既然如此,对于一切全局变量要么用 static限死,要么定义同时初始化,杜绝弱符号,以便在编译时报错检测出来。只要小心地使用,C语言还是很完美的嘛~对于抱这样想法的人,我只想说, 请你在夜深人静的时候竖起耳朵仔细聆听,你很可能听到Dennis Richie在九泉之下邪恶的笑声——不,与其说是嘲笑,不如说是诅咒 第四个例子
/* foo.c */ #include <stdio.h> const struct { int a; int b; } b = { 3, 3 }; int main();
void foo()
{
b.a = 4;
b.b = 4;
printf("foo:\t(&b)=0x%08x\n\tsizeof(b)=%d\n
\tb.a=%d\n\tb.b=%d\n\tmain:0x%08x\n",
&b, sizeof b, b.a, b.b, main);
}
/* t1.c */
#include <stdio.h>
int b = 1;
int c = 1;
int main()
{
int count = 5;
while (count-- > 0) {
t2();
foo();
printf("t1:\t(&b)=0x%08x\n\t(&c)=0x%08x\n
\tsizeof(b)=%d\n\tb=%d\n\tc=%d\n",
&b, &c, sizeof b, b, c);
sleep(1);
}
return 0;
}
/* t2.c */
#include <stdio.h>
int b;
int c;
int t2()
{
printf("t2:\t(&b)=0x%08x\n\t(&c)=0x%08x\n
\tsizeof(b)=%d\n\tb=%d\n\tc=%d\n",
&b, &c, sizeof b, b, c);
return 0;
}
Makefile脚本:
export LD_LIBRARY_PATH:=.
all: test
./test
test: t1.o t2.o
gcc -shared -fPIC -o libfoo.so foo.c
gcc -o test t1.o t2.o -L. -lfoo
t1.o: t1.c
t2.o: t2.c
.PHONY:clean
clean:
rm -f *.o *.so test*
执行结果:
./test
t2: (&b)=0x0804a01c
(&c)=0x0804a020
sizeof(b)=4
b=1
c=1
foo: (&b)=0x0804a01c
sizeof(b)=8
b.a=4
b.b=4
main:0x08048564
t1: (&b)=0x0804a01c
(&c)=0x0804a020
sizeof(b)=4
b=4
c=4
t2: (&b)=0x0804a01c
(&c)=0x0804a020
sizeof(b)=4
b=4
c=4
foo: (&b)=0x0804a01c
sizeof(b)=8
b.a=4
b.b=4
main:0x08048564
t1: (&b)=0x0804a01c
(&c)=0x0804a020
sizeof(b)=4
b=4
c=4
... 其实前面几个例子只是开胃小菜而已,真正的大坑终于出现了!而且这次编译器既没报错也没警告,但我们确实眼睁睁地看到作为main()中强符号的b 被改写了,而且一旁的c也“躺枪”了。眼尖的读者发现,这次foo.c是作为动态链接库运行时加载的,当t1第一次调用t2时,libfoo.so还未加 载,一旦调用了foo函数,b立马中弹,而且c的地址居然还相邻着b,这使得c一同中弹了。不过笔者有些无法解释这种行为的原因,有种说法是强符号的全局变量在数据段中是连续分布的(相应地弱符号暂存在.bss段或者符号表里),或许可以上报GNU的编译器开发小组。
另外笔者尝试过将t1.c中的b和c定义前面加上const限定词,编译器仍然默认通过,但程序在main()中第一次调用foo()时触发了Segment fault异常导致奔溃,在foo.c里使用指针改写它也一样。推断这是GCC对const常量所在地址启用了类似操作系统写保护机制,但我无法确定早期版本的GCC是否会让这个const常量被改写而程序不会奔溃。
至于volatile关键词之于全局变量,自测似乎没有影响。
怎么样?看了最后一个例子是否有点“不明觉厉”呢?C语言在你心目中是否还是当初那个“纯洁”、“干净”、“行为一致”的姑娘呢?也许趁着你不注意 的时候她会偷偷给你戴顶绿帽,这一切都是通过全局变量,特别在动态链接的环境下,就算全部定义成强符号仍然无法为编译器所察觉。而一些IT界“恐怖分子” 也经常将恶意代码包装成全局变量注入到root权限下存在漏洞的操作序列中,就像著名的栈溢出攻击那样。某一天当你傻傻地看着一个程序出现未定义的行为却无法定位原因的时候,请不要忘记Richie大爷那来自九泉之下最深沉的“问候”~
或许有些人会偷换概念,把这一切归咎于编译器和链接器身上,认为这同语言无关,但我要提醒你,正是编译/链接器的行为支撑了整个语言的语法和语义。你可以反过来思考一下为何C的胞弟C++推出“命名空间(namespace)”的概念,或者你可以使用其它高级语言,对于重定义的全局变量是否能通过编译这一关。
所以请时刻谨记,C是一门很恐怖的语言!
P.S.题外话写在最后。我无意挑起语言之争,只是就事论事地去“黑(hack)”一门语言而已,而且要黑就要黑得有理有力有层次,还要带点娱乐精神。其实黑一门语言并非什么尖端复杂的技术,个人觉得起码要做到两点:
亲自动手写测试程序。动手写测试程序是开发人员必备的基础技能,只有现成的代码才能让人心服口服,那些只会停留在口头上的争论只能算作cheap hack。
测试程序不能依赖于不成熟的代码。软件开发99%以上的bug都是基于不合格(substandard)开发 人员导致,这并不能怪罪于语言以及编译器本身。使用诸如#define TRUE FALSE或者#define NULL 1之类的trick来黑C语言只能证明此人很有娱乐精神而不是真正的”hack value”,拿老北京梨园行当里的一句话——“那是下三滥的玩意儿”。
正在阅读:
C语言全局变量那些事儿(2)07-22
工程化学205-02
《金刚经》的现代意义05-31
生命的起点作文600字06-29
商铺租赁协议书10-13
河南郑州中牟县人民医院临时工考试真题07-22
继续教育抗菌药物临床合理应用答案07-29
尔雅世界建筑考试答案06-06
预防电力变压器渗漏油的措施05-21
英语泛读四vocabulary选择和填空05-12
- 教学能力大赛决赛获奖-教学实施报告-(完整图文版)
- 互联网+数据中心行业分析报告
- 2017上海杨浦区高三一模数学试题及答案
- 招商部差旅接待管理制度(4-25)
- 学生游玩安全注意事项
- 学生信息管理系统(文档模板供参考)
- 叉车门架有限元分析及系统设计
- 2014帮助残疾人志愿者服务情况记录
- 叶绿体中色素的提取和分离实验
- 中国食物成分表2020年最新权威完整改进版
- 推动国土资源领域生态文明建设
- 给水管道冲洗和消毒记录
- 计算机软件专业自我评价
- 高中数学必修1-5知识点归纳
- 2018-2022年中国第五代移动通信技术(5G)产业深度分析及发展前景研究报告发展趋势(目录)
- 生产车间巡查制度
- 2018版中国光热发电行业深度研究报告目录
- (通用)2019年中考数学总复习 第一章 第四节 数的开方与二次根式课件
- 2017_2018学年高中语文第二单元第4课说数课件粤教版
- 上市新药Lumateperone(卢美哌隆)合成检索总结报告
- 全局
- 变量
- 事儿
- 那些
- 语言
- 第六章时序逻辑电路的分析和设计
- QQ炫舞抓猪模式问题答案
- 东京理科大学成功开发出适合电动汽车使用的开关磁阻电机
- 2012年家装设计行业薪酬现状分析
- 保护野生动物 save the wildlife
- 人教版八年级下学期数学期末测试题(3)
- 2017宁德市质检语文试卷及答案
- 防撞护栏施工方案
- 冷轧板的各工序形貌及表面清洁度分析
- 教科版小学四年级科学下册复习资料
- 白芍总甙对大鼠酒精性肝损伤保护作用的实验研究
- 北魏孝文帝的改革措施
- 2015-2016学年高二上学期第二阶段考试生物(理)试卷
- 学校星摆POSE 咔嚓咔嚓~~美呆了
- 121团第二中学班主任绩效考核细则(讨论稿)
- 2018年期货从业考试法律法规知识点整理
- 高中生物浙科版必修二 第四章 第二节 生物变异在生产上的应用
- 空气细菌培养的采样方法
- 鱼雷发射装置实现同舷信息通道组织研究
- 河南郑州中牟县人民医院临时工考试真题