Fab*_*era 12 c++ linker templates g++
想象一下你有一个文件啊
#include <iostream>
template<typename T> struct A{
int magic;
A():magic(1234){}
void f(){std::cout<<"default f"<<magic<<std::endl;}
};
void f(A<int>* a);
Run Code Online (Sandbox Code Playgroud)
然后函数f在"a.cpp"中定义
#include "a.h"
void f(A<int>* a){
a->f();
}
Run Code Online (Sandbox Code Playgroud)
最后,"main.cpp"专门化模板,然后使用f
#include "a.h"
template<> struct A<int>{
};
int main(){
A<int> a;
f(&a);
}
Run Code Online (Sandbox Code Playgroud)
很明显,编译器使用非专用版本的ao,以及main.o的专用版本,即恰好有两种不同的A实现.执行时,f只能打印垃圾/段错误,因为传递的对象具有不同的结构从预期的.
有没有办法让链接器警告有两个版本的A?
Gold 不对此发出警告的原因是 Gold 只检测符号不匹配(同一符号以不兼容的方式在多个目标文件中定义),并且示例中不存在此类不匹配。
在 Valgrind 下运行示例确实会产生此错误:
valgrind --track-origins=yes ./a.out
==11004== Memcheck, a memory error detector
==11004== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==11004== Using Valgrind-3.8.0.SVN and LibVEX; rerun with -h for copyright info
==11004== Command: ./a.out
==11004==
==11004== Conditional jump or move depends on uninitialised value(s)
==11004== at 0x40B6D24: std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib64/libstdc++.so.6.0.16)
==11004== by 0x40B703C: std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::do_put(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib64/libstdc++.so.6.0.16)
==11004== by 0x40C26DE: std::ostream& std::ostream::_M_insert<long>(long) (in /usr/lib64/libstdc++.so.6.0.16)
==11004== by 0x40094F: A<int>::f() (a.h:6)
==11004== by 0x4008CB: f(A<int>*) (a.cpp:3)
==11004== by 0x400977: main (main.cpp:7)
==11004== Uninitialised value was created by a stack allocation
==11004== at 0x400964: main (main.cpp:5)
Run Code Online (Sandbox Code Playgroud)
您应该从Address Sanitizer获得更好的报告:
更新:
重点是我想在链接时而不是在执行期间检测错误。
我理解您的观点,但目前编译器(没有有关其他翻译单元的信息)或链接器(没有有关所涉及类型的信息)无法警告您这一点。
现在,对于调试构建,理论上链接器可以做到这一点,如果对于每个函数它还比较参数类型的调试信息。我建议在bugzilla中提交黄金功能请求。