g ++,需要链接器警告/错误才能进行多个模板专业化

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?

Emp*_*ian 3

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中提交黄金功能请求。