链接器多重定义错误:为啥 <thread> 似乎定义了我的函数?

Posted

技术标签:

【中文标题】链接器多重定义错误:为啥 <thread> 似乎定义了我的函数?【英文标题】:Linker multiple definition error: Why does <thread> seem to define my functions?链接器多重定义错误:为什么 <thread> 似乎定义了我的函数? 【发布时间】:2017-04-20 11:49:41 【问题描述】:

在构建我的项目时,我收到以下错误消息。不幸的是,我无法理解它。

CMakeFiles/xxx.dir/xxx/send_dummy_events.cc.o: In function `std::chrono::duration_values<long>::zero()':
/usr/include/c++/6/thread:311: multiple definition of `POLONAISE::xxx::dispatch_event(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
CMakeFiles/xxx.dir/xxx/main.cc.o:/home/manuel/projects/projectname/build_x86_64/package/xxx/send_dummy_events.cc:10: first defined here

CMakeFiles/xxx.dir/xxx/send_dummy_events.cc.o: In function `std::chrono::duration<long, std::ratio<1l, 1000000000l> >::count() const':
/usr/include/c++/6/thread:311: multiple definition of `POLONAISE::xxx::send_dummy_events()'
CMakeFiles/xxx.dir/xxx/main.cc.o:/home/manuel/projects/projectname/build_x86_64/package/xxx/send_dummy_events.cc:16: first defined here

在我看来,/usr/include/c++/6/thread 似乎会重新定义我的函数名称 dispatch_event()send_dummy-event()

我的send_dummy_events.cc的来源是这样的:

#include <chrono>
#include <thread>
#include "POLONAISE/logging.h"
#include "POLONAISE/EventQueue.h"


namespace POLONAISE 
    namespace xxx 
        void dispatch_event(std::string serialized_uirequest __attribute__((unused)))
        

                   


        void send_dummy_events()
        
            std::chrono::seconds delay(3);
            while (1) 
                    std::this_thread::sleep_for(delay);
            
        
    

usr/include/c++/6/thread 的来源是这样的:(不要被行号弄糊涂了,我忘了如何在 Vim 中关闭它们。)

     /// sleep_for
  2     template<typename _Rep, typename _Period>
  1       inline void
311       sleep_for(const chrono::duration<_Rep, _Period>& __rtime)
  1       
  2         if (__rtime <= __rtime.zero())
  3           return;
  4         auto __s = chrono::duration_cast<chrono::seconds>(__rtime);
  5         auto __ns = chrono::duration_cast<chrono::nanoseconds>(__rtime - __s);
  6 #ifdef _GLIBCXX_USE_NANOSLEEP
  7         __gthread_time_t __ts =
  8           
  9             static_cast<std::time_t>(__s.count()),
 10             static_cast<long>(__ns.count())
 11           ;
 12         while (::nanosleep(&__ts, &__ts) == -1 && errno == EINTR)
 13            
 14 #else
 15         __sleep_for(__s, __ns);
 16 #endif
 17       

【问题讨论】:

多重定义错误通常意味着您在没有包含保护的头文件中定义了代码,或者您将源文件包含在另一个文件中。 @Someprogrammerdude 是的,但如果它们被包含在链中而没有意识到它们的存在,那么拥有它们并没有什么坏处。 @CIsForCookies 如果你在两个源文件中定义一个同名函数,从这两个源文件创建目标文件,然后将目标文件链接在一起,你将在两个 @ 中定义相同的符号987654321@ 给出了像多重定义这样的链接器错误。函数(或任何其他符号)来自头文件并不重要。 @Someprogrammerdude 所以,如果 A.c 和 B.c 都包含定义 'void foo()' 的 H.h 然后链接对象 O_a 和 O_b 链接器将无法理解 O_a 中的 'foo' i> 和 'foo' 一样 n O_b? @CIsForCookies 没错。 【参考方案1】:

我找到了原因,现在正在回答我自己的问题:

根本原因是,在main.cc#included send_dummy_events.cc。由于这只是一个临时测试存根,几周前我没有看到任何问题。但是现在我为应用程序的新部分复制了现有代码,并且在更新CMakeLists.txt 时,我只是确保在那里记录了每个源文件。所以我加了send_dummy_events.cc

瞧,由于链接器现在两次得到相同的符号,他抱怨它是正确的。

现在我听说甚至有一条关于此的规则:永远不要包含源文件。好吧,我知道为什么了。

我仍然对为什么错误消息读起来好像第二个定义会出现在 /usr/include/c++/6/thread 感到困惑,但我想这只是 GCC 众所周知的另一个“令人困惑的错误消息™”。

【讨论】:

以上是关于链接器多重定义错误:为啥 <thread> 似乎定义了我的函数?的主要内容,如果未能解决你的问题,请参考以下文章

未定义对向量<String> g++ 链接器错误的引用[重复]

从 AfxGetAppModuleState 更改为 AfxGetStaticModuleState 会导致链接器错误:LNK1169:找到一个或多个多重定义的符号

linux 静态链接和动态链接

链接器错误:未定义的函数引用

与 DLL 链接时出现“‘atexit’的多重定义”

链接器错误,使用 g++ 链接到由 gcc 编译的库,未定义对该函数的引用