在新 OS 上编译时遗留代码提供核心转储

Legacy code giving core dump when compiled on new OS

我正在处理遗留 c/c++ 项目。该项目最初是在 UNIX 上,然后他们在多年前迁移到 Linux。 现在,我们升级到 RHEL 7.9。自从我们升级后,我们用新的依赖库编译了所有旧代码。 该代码具有以下内容...

#include <pwd.h>
...
{
    struct passwd   *pwd;
    ...
    ...
    // U2L commented for skiping ACMgetpwuid
    //  if ((pwd = ACMgetpwuid(primuid)) == NULL)
    ...
    
    if (strlen_u2l(pwd->pw_passwd) == 0) {    
    ...
    }

此代码仍在生产中,它是 运行 RHEL 7 并且工作正常(我相信他们在 RHEL 5 上编译,同样在 RHEL 7 上运行并且工作正常)。如您所见,他们没有分配任何内存,也忘记了 if 块的注释,他们正在访问 pwd->pw_passwd。 但是当我们现在在新的 RHEL 7 上编译相同的代码时,相同的代码正在提供核心转储。

为什么相同的代码在 RHEL 7 上编译时会产生核心转储? 但是旧的编译二进制文件(在 RHEL 5 上编译)没有在 RHEL 7 上提供核心转储。我是 UB 的受害者吗?

由于通过未初始化的指针取消引用,您是 undefined behavior 的受害者。

看来注释掉 pwd = ACMgetpwuid(primuid) 的人破坏了后面的代码。至少他们应该注释掉两个 if 语句。

pwd是未初始化的,所以它的值是不确定的;它可以取决于堆栈上或某个寄存器中的先前字节。先前的值是什么可以取决于 OS、编译器版本、使用的编译标志、当前程序状态,即几乎任何东西。

有些编译器甚至省略了指向 UB 的整个代码段(如 if (strlen_u2l(pwd->pw_passwd) == 0)),甚至不屑于为此类函数发出 return 指令。