Upgrading GCC version leads to program crashes: Hidden dangers of non-compliant code

The program compiled and ran normally in the CentOS 7 environment, but crashed when switched to CentOS 8 and compiled with a newer version of GCC. Notably, this issue only occurred under Release 模式, while Debug 模式 was unaffected. This was the first time we encountered such a situation, and after three days of troubleshooting, we finally found the root cause.

Issue identification

The root cause of the problem lies in 函数缺少返回值. The increased optimization performed by newer versions of GCC in Release mode has introduced unknown logic into functions without explicit return values, leading to crashes. Our conclusion is that 编译器的警告不容忽视,尤其是在老项目中,部分警告可能被无视,但也应当避免屏蔽所有警告.

Environmental Description

  • Please provide the Chinese text you want me to translate. I am ready when you are!

    gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-39)
    Copyright © 2015 Free Software Foundation, Inc.
    
  • Please provide the Chinese text you want me to translate. I am ready when you are!

    gcc (GCC) 8.5.0 20210514 (Red Hat 8.5.0-21)
    Copyright (C) 2018 Free Software Foundation, Inc.
    

Crash phenomenon

When analyzing the program crash stack, we observed the following stack information:

[New LWP 1385902]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Core was generated by `./pstack_main`.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007ffe894b4420 in ?? ()
(gdb) bt
#0  0x00007ffe894b4420 in ?? ()
#1  0x00000000004008e9 in main ()

This stack trace isn’t intuitive; the crash information shows as a __INLINE_CODE_0, making debugging more difficult

Code example

To better understand the issue, here’s a minimal code example to reproduce the crash:

#include <iostream>
#include <map>

int test() {
    std::cout << "1" << std::endl;
}

int main() {
    test();
    return 0;
}

When a ``test() 函数显然没有显式返回一个值,而它的返回类型是 __INLINE_CODE_1__。根据 C++ 规范,当一个函数声明为 __INLINE_CODE_2__ type is used, it must have a return value; otherwise, undefined behavior may occur

Compilation warning

In our project, CMake scripts suppress many compile-time warnings, including the following message:

/root/pstack/main.cpp: In function ‘int test()’:
/root/pstack/main.cpp:7:1: warning: no return statement in function returning non-void [-Wreturn-type]

This warning indicates that the INLINE_CODE_0 function has no return value, which is the root of the problem. High-version GCC (such as 8.5.0) may perform unstable optimizations on this undefined behavior during code optimization, leading to program crashes.

Assembly code differences

To explain the differences in GCC compiler optimization behavior, we compared assembly code generated by different versions of GCC

  • Please provide the Chinese text you want me to translate. I am ready when you are!

The assembly code is lengthy and includes excessive optimizations for issues like the missing return value in functions such as __INLINE_CODE_0__BOLD_2test(), which may have prevented a crash

  • Please provide the Chinese text you want me to translate. I am ready when you are!

The new version of GCC includes more optimizations that reduce code size. However, these optimizations can lead to undefined behavior when executing functions lacking return values, potentially causing program crashes.

Conclusion

This troubleshooting has highlighted the importance of carefully addressing warnings in C++, particularly when functions are declared inline. It’s crucial to selectively handle these warnings, especially those related to function return values and type matching, rather than suppressing them all.

The issue was resolved by adding a return value to the INLINE_CODE_0 function, and the program returned to normal operation

A financial IT programmer's tinkering and daily life musings
Built with Hugo
Theme Stack designed by Jimmy