遗留C/C++代码在RHEL7.9编译后core dump,旧RHEL5编译版本运行正常?
问题解答
首先明确结论:你遇到的是典型的未定义行为(Undefined Behavior, UB)。C/C++标准明确规定,访问未初始化的野指针属于UB,程序的运行表现没有任何确定性,出现任何结果(包括看似正常运行、崩溃、数据错乱)都符合UB的特征。
两种场景表现不同的原因
1. RHEL5编译的旧版本在RHEL7运行正常的原因
局部指针变量pwd分配在栈内存上,未显式初始化时,它的取值就是栈内存当前残留的历史数据:
- RHEL5自带的GCC版本(通常是GCC 4.1.x)的栈帧布局规则、栈内存使用逻辑和RHEL7的GCC差异很大,旧编译器生成的二进制在运行时,执行到
pwd->pw_passwd访问逻辑时,栈上残留的pwd值刚好是一个合法的、用户态可访问的内存地址,且该地址对应struct passwd结构的pw_passwd偏移位置刚好存储了合法的字符串,因此不会触发段错误。 - 同时RHEL5时代的编译选项默认不会开启栈保护、栈随机化等安全机制,运行时栈内存布局的稳定性更高,刚好踩中合法地址的概率更高。
2. RHEL7重新编译后触发core dump的原因
RHEL7自带的GCC版本为GCC 4.8.x,默认的编译和运行安全策略都有很大变化:
- GCC默认开启了
-fstack-protector栈保护、未初始化变量自动填充非法值等逻辑,此时栈上未初始化的pwd指针的取值大概率是非法地址(比如0地址、内核禁止用户态访问的地址段),访问该地址时会直接触发段错误,生成core dump。 - RHEL7的ASLR(地址空间布局随机化)强度远高于RHEL5,也会导致旧版本中刚好合法的地址在新编译的程序中变为不可访问。
修复建议
- 恢复被注释的
ACMgetpwuid赋值逻辑,或补充pwd指针的合法初始化逻辑,且访问指针成员前必须先判断指针非空。 - 编译时开启
-Wall -Wuninitialized等告警选项,可在编译阶段直接识别出未初始化指针访问的问题,提前规避此类故障。
内容的提问来源于stack exchange,提问作者NJMR
相关产品推荐
相关产品推荐

