【问题标题】:Strange gcc Initialization crash on old macs旧 Mac 上奇怪的 gcc 初始化崩溃
【发布时间】:2018-05-26 10:23:06
【问题描述】:

下面的代码在旧的 ppc mac 上编译时崩溃(代码下面的崩溃日志)。在较新的 Mac 上,它会打印一个空行和“测试”。我可以理解可能无法保证 test::mName 初始化的顺序和全局 test obj 的初始化(在实际代码中它们在不同的文件中),但似乎在旧 mac 上,mName 在调用构造函数时的某种部分初始化状态。这段代码是无效还是编译器有问题?

#include <iostream>
#include <string>

class test
{
public:
  test();
  static std::string mName;
};

test obj;

std::string test::mName("Test");

test::test()
{
  std::cout << mName << std::endl;
}

int main(int argc, char *argv[])
{
  std::cout << obj.mName << std::endl;
  return 0;
}

崩溃日志:

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x00000000fffffff4
Crashed Thread:  0

Thread 0 Crashed:
0   libstdc++.6.dylib                   0x90aa4268 std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char,std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char,std::char_traits<char> >&, std::basic_string<char,std::char_traits<char>, std::allocator<char> > const&) + 64
1   crash                               0x00001b28 test::test() + 48
2   crash                               0x00001de0 __static_initialization_and_destruction_0(int, int) + 144
3   crash                               0x00001e98 _GLOBAL__I_obj + 32
4   dyld                                0x8fe13830 ImageLoaderMachO::doModInitFunctions(ImageLoader::LinkContext const&) + 252
5   dyld                                0x8fe0f244 ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int) + 384
6   dyld                                0x8fe0f368 ImageLoader::runInitializers(ImageLoader::LinkContext const&) + 60
7   dyld                                0x8fe03844 dyld::initializeMainExecutable() + 132
8   dyld                                0x8fe08140 dyld::_main(mach_header const*, unsigned long, int, char const**, char const**, char const**) + 3420
9   dyld                                0x8fe01770 dyldbootstrap::start(mach_header const*, int, char const**, long) + 988
10  dyld                                0x8fe01044 _dyld_start + 56

【问题讨论】:

    标签: macos gcc compiler-errors initialization powerpc


    【解决方案1】:

    在您的示例中,testtest::mName 之前定义,因此首先执行其构造函数,并且在test::test() 构造函数中对test::mName 的访问是未定义的。如果它不会导致其他架构崩溃,那纯属偶然。

    【讨论】:

    • 感谢您的回复。那么这是否意味着您不能在构造函数中使用任何静态类成员变量,因为有人可能会将您的类用作全局变量,并且编译器可能决定在初始化该类的静态成员变量之前初始化该全局变量?我从未听说过这条规则,也从未在现代编译器中看到过任何警告或错误。
    • 搜索全局构造函数顺序。这是一个相当知名的 C++ 问题。
    • 在我发布的示例代码中,顺序是明确定义的,但正如我在原始问题中所说,在原始代码中,类和全局变量位于单独的文件中,因此顺序未定义。那么在这种情况下你不能在构造函数中使用静态类成员变量吗?
    • 看来你不能在构造函数中使用静态类成员变量(为什么现代编译器不为此给出警告或错误?):isocpp.org/wiki/faq/ctors#static-init-order
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-20
    • 2011-02-22
    相关资源
    最近更新 更多