gcc 升级导致模板函数的静态局部变量变得未知
Posted
技术标签:
【中文标题】gcc 升级导致模板函数的静态局部变量变得未知【英文标题】:gcc upgrade caused static local variable of template function to become unknow 【发布时间】:2017-07-04 07:23:14 【问题描述】:我正在将我们的 gcc 从 gcc 4.1.2 升级到 gcc 4.9.4。
我先用gcc4.9编译,然后启动程序,看到如下错误:
user@machine:~/bin> Load BusinessSoCfg, Name GameSvr, Dll ../SO/so, CreateFunc CreateBusinessSo
Open Dll ../SO/so failed, ../SO/so: undefined symbol: _ZZN6CTable24IsGameTableSOSupportFuncIM5IGameFiisiiP13tagSOItemInfoEEEbT_E7pHandle
pHandle 是模板函数中定义的静态变量。 代码是这样的:
template<class TPMF>
bool CTable::IsGameTableSOSupportFunc(TPMF pfunc)
static void *pHandle = NULL;
// somethign todo
return true;
在我们的测试环境(gcc4.1.2)中,nm -C 显示如下,表示符号是未知类型
0000000004d1d9d0 ? bool CTable::IsGameTableSOSupportFunc<int (IGame::*)(int, short, int, int, tagSOItemInfo*)>(int (IGame::*)(int, short, int, int, tagSOItemInfo*))::pHandle
但在编译 env(gcc4.9.4) nm -C 时显示如下,显示符号已定义
0000000004d1d9d0 u bool CTable::IsGameTableSOSupportFunc<int (IGame::*)(int, short, int, int, tagSOItemInfo*)>(int (IGame::*)(int, short, int, int, tagSOItemInfo*))::pHandle
更重要的是,gcc4.9.4 是使用 gcc4.1.2 从源代码编译而来的,配置如下:
$ ./configure --prefix=/data/gcc-4.9.4/ --enable-languages=c,c++ --enable-lto --enable-vtable-verify --disable-libquadmath-support --disable-libada
原因:以下示例显示的结果与上述不同
示例:
//singleton.hpp, must be a hpp
// if singleton was defined in the same file with main,everything goes fine
#include <stdio.h>
#include <stdlib.h>
template <class TYPE>
class CSingleton
public:
static TYPE* Instance(void)
if(m_pSingleton == NULL)
CSingleton *pTmpCSingleton = new CSingleton;
m_pSingleton = pTmpCSingleton;
return &m_pSingleton->m_stInstance;
protected:
TYPE m_stInstance;
static CSingleton<TYPE>* m_pSingleton;
;
template <class TYPE>
CSingleton<TYPE>* CSingleton<TYPE>::m_pSingleton = NULL;
// main.cpp
// if singleton was defined in the same file with main,everything goes fine
#include "singleton.hpp"
#include <stdio.h>
typedef CSingleton<int> s;
int main()
printf("%d\n", *s::Instance());
return 0;
用gcc4.9编译,运行结果为:0
但是当我将二进制文件复制到 gcc4.1.2 机器时,执行将成为核心。
Floating point exception (core dumped)
fathermore nm -C 会显示一些错误:
nm: a.out: File format not recognized
但两台机器上的 readelf 都可以正常工作:
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x400520
Start of program headers: 64 (bytes into file)
Start of section headers: 3072 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 8
Size of section headers: 64 (bytes)
Number of section headers: 30
Section header string table index: 27
【问题讨论】:
编译器的错误? 因为我不确定如何从源代码升级 gcc。我仍然想知道它是否是由坏的 gcc/g++ 工具链引起的。 你能创建一个SSCCE吗? 添加了一个简单的sscce,它将在旧机器上核心 你的例子和你上面写的不一样 【参考方案1】:这是由 gcc 升级引起的。从更高版本的 gcc 编译的二进制文件使用 gnu 哈希。但是正在运行的计算机的 binutil 无法识别这一点。用-Wl,--hash-style=both
或-Wl,--hash-style=sysv
重新编译可以解决这个问题。
如果我早点查看核心文件,我可以更快地解决这个问题。
【讨论】:
以上是关于gcc 升级导致模板函数的静态局部变量变得未知的主要内容,如果未能解决你的问题,请参考以下文章