如果兩個變數在不同的源檔案中具有相同的型別和名稱,則聯結器命令失敗并出現重復符號錯誤,盡管兩個源檔案不相關。
這是我的專案結構。
CMakeLists.txt
cmake_minimum_required(VERSION 3.0.0)
project(duplicate-symbol-test VERSION 0.1.0)
add_executable(duplicate-symbol-test main.cpp a.hpp a.cpp b.hpp b.cpp)
target_compile_features(duplicate-symbol-test PUBLIC cxx_std_17)
a.hpp
#pragma once
struct A{
int getRandomNumber() const;
};
a.cpp
#include "a.hpp"
#include <random>
std::random_device rd;
std::mt19937 gen { rd() };
std::uniform_int_distribution<int> dis { 0, 100 };
int A::getRandomNumber() const{
return dis(gen);
}
b.hpp
#pragma once
struct B{
int getRandomNumber() const;
};
b.cpp
#include "b.hpp"
#include <random>
std::random_device rd;
std::mt19937 gen { rd() };
std::uniform_int_distribution<int> dis { 0, 100 };
int B::getRandomNumber() const{
return dis(gen);
}
main.cpp
#include <iostream>
#include "a.hpp"
#include "b.hpp"
int main(int, char**) {
A a;
std::cout << a.getRandomNumber() << std::endl;
B b;
std::cout << b.getRandomNumber() << std::endl;
return 0;
}
構建時,cmake 構建系統顯示,
[主] 構建檔案夾:duplicate-symbol-test
[構建] 開始構建
[proc] 執行命令:/opt/homebrew/bin/cmake --build /Users/admin/Desktop/duplicate-symbol-test/build --config Debug --target all --
[構建] [1/2 50% :: 0.661] 構建 CXX 物件 CMakeFiles/duplicate-symbol-test.dir/b.cpp.o
[構建] [2/2 100% :: 0.742] 鏈接 CXX 可執行檔案重復符號測驗
[構建] 失敗:重復符號測驗
[構建] : && /opt/homebrew/opt/llvm/bin/clang -g -arch arm64 -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX12.3.sdk -Wl,-search_paths_first -Wl,-headerpad_max_install_names CMakeFiles/重復符號測驗.dir/main.cpp.o CMakeFiles/重復符號測驗.dir/a.cpp.o CMakeFiles/重復符號測驗.dir/b.cpp.o -o 重復符號測驗&& :
[構建]重復符號 '_dis' 在:
[構建] CMakeFiles/duplicate-symbol-test.dir/a.cpp.o
[構建] CMakeFiles/duplicate-symbol-test.dir/b.cpp.o
[構建]重復符號 '_gen' 在:
[構建] CMakeFiles/duplicate-symbol-test.dir/a.cpp.o
[構建] CMakeFiles/duplicate-symbol-test.dir/b.cpp.o
[構建]重復符號 '_rd' 在:
[構建] CMakeFiles/duplicate-symbol-test.dir/a.cpp.o
[構建] CMakeFiles/duplicate-symbol-test.dir/b.cpp.o
[build] ld:架構 arm64 的 3 個重復符號
[build] clang-14:錯誤:聯結器命令失敗,退出代碼為 1(使用 -v 查看呼叫)
[構建]忍者:構建停止:子命令失敗。
[proc] 命令:/opt/homebrew/bin/cmake --build /Users/admin/Desktop/duplicate-symbol-test/build --config Debug --target all -- 退出代碼:1 和信號:null
[構建] 構建完成,退出代碼 1
我該如何解決?
uj5u.com熱心網友回復:
我該如何解決?
通過使所有符號本地化到其翻譯單元。全域非常量變數默認具有外部鏈接,因此具有相同限定名的兩個變數在鏈接期間會發生沖突。
這可以通過以下任一方式解決:
- 宣告它們
static- 強制內部鏈接。 - 將它們放入匿名命名空間 - 確保唯一的限定名稱。
我推薦第二個選項,因為它也適用于型別:
namespace{
std::random_device rd;
std::mt19937 gen { rd() };
std::uniform_int_distribution<int> dis { 0, 100 };
}
int B::getRandomNumber() const{
return dis(gen);
}
與問題無關,但通常沒有理由保留rd,std::mt19937 gen { std::random_device{}() };也可以。請注意,這random_device可能是確定性的并且每次都產生相同的序列,請檢查您的實作。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/511333.html
標籤:C 建造重复链接器符号
