晚上好!
在使用一个名为kodo的项目期间,我的链接器告诉我几个函数的多个定义。该项目由施泰因沃夫开发,用于在中实现随机线性网络编码。make的输出引用如下:
Creating executable: out/gcc-debug//simulation
./libs/boost/libboost_thread.a(once_atomic.cpp.1.o): In Funktion
`boost::thread_detail::enter_once_region(boost::once_flag&)':
once_atomic.cpp:(.text+0x0): Mehrfachdefinition von
boost::thread_detail::enter_once_region(boost::once_flag&)'
./libs/boost/libboost_thread.a(once.cpp.1.o):once.cpp:(.text+0x0): first
efined here
./libs/boost/libboost_thread.a(once_atomic.cpp.1.o): In Funktion
`boost::thread_detail::commit_once_region(boost::once_flag&)':
once_atomic.cpp:(.text+0x150): Mehrfachdefinition von
boost::thread_detail::commit_once_region(boost::once_flag&)'
./libs/boost/libboost_thread.a(once.cpp.1.o):once.cpp:(.text+0x150): first defined here
./libs/boost/libboost_thread.a(once_atomic.cpp.1.o): In Funktion
boost::thread_detail::rollback_once_region(boost::once_flag&)':
once_atomic.cpp:(.text+0x1e0): Mehrfachdefinition von
boost::thread_detail::rollback_once_region(boost::once_flag&)'
./libs/boost/libboost_thread.a(once.cpp.1.o):once.cpp:(.text+0x1e0): first defined here
/usr/bin/ld: ./libs/gtest/libgtest.a(gtest-all.cc.1.o): undefined
reference to symbol 'pthread_key_delete@@GLIBC_2.2.5'
//lib/x86_64-linux-gnu/libpthread.so.0: error adding symbols: DSO aus der Kommandozeile fehlt
collect2: error: ld returned 1 exit status
Makefile:111: die Regel für Ziel „out/gcc-debug//simulation“ scheiterte
make: *** [out/gcc-debug//simulation] Fehler 1如您所见,还有几个其他的多个定义和一个无法识别的库(libgtest.a)。
kodo-rlnc从1下载并按照Steinwurf-文件的指示编译,下载自己的依赖项,也在3.中列出。
现在在我看来,boost库本身出现了故障,产生了多个定义错误。但是由于我不是C++程序员的专家,所以我可能会监督一些细节。我将在下面发布我的代码,但请注意包含-部分和Quelle::send_rlnc()函数,它使用kodo-rlnc。您会注意到,最初调用的Quelle::initialize()函数没有使用它。链接的问题发生在使用它的功能之前。(这很标准)。下面是我用包含的kodo编写的代码:
#include<omnetpp.h>
#include<string.h>
#include<stdlib.h>
#include<vector>
#include<random>
#include<functional>
#include<map>
#include<iterator>
#include<algorithm>
#include<fstream>
#include <cstdint>
#include <iostream>
#include "payload_packet_m.h"
#include<kodo_core/object/file_encoder.hpp>
#include <kodo_rlnc/full_vector_codes.hpp>
#include<kodocpp/kodocpp.hpp>
#include<kodoc/kodoc.h>
using namespace omnetpp;
class Quelle : public cSimpleModule{
private:
//uint32_t max_symbols;
//uint32_t max_symbol_size;
int is_rlnc;
std::vector<uint8_t> readFile(const char* filename);
void send_rlnc();
void send_lnc();
protected:
virtual int calculate_vector_checksum(std::vector<unsigned int> input);
virtual void initialize() override;
virtual void handleMessage(cMessage *msg) override;
};
Define_Module(Quelle);
std::vector<uint8_t> Quelle::readFile(const char* filename){
std::ifstream file("testfile.txt", std::ios::binary);
file.unsetf(std::ios::skipws);
std::streampos fileSize;
file.seekg(0, std::ios::end);
fileSize = file.tellg();
file.seekg(0, std::ios::beg);
std::vector<uint8_t> vec;
vec.reserve(fileSize);
vec.insert(vec.begin(),
std::istream_iterator<uint8_t>(file),
std::istream_iterator<uint8_t>());
return vec;
}
int Quelle::calculate_vector_checksum(std::vector<unsigned int> input){
int checksum = 0;
std::vector<unsigned int>::iterator It;
for(It = input.begin(); It != input.end(); It++){
checksum += *It;
}
return checksum;
}
void Quelle::send_rlnc(){
uint32_t max_symbols = 16; //par("max_symbols");
uint32_t max_symbol_size = 1400; //par("max_symbol_size");
fifi::api::field field = fifi::api::field::binary8;
using rlnc_encoder = kodo_rlnc::full_vector_encoder;
using rlnc_decoder = kodo_rlnc::full_vector_decoder;
rlnc_encoder::factory encoder_factory(field, max_symbols, max_symbol_size);
auto encoder = encoder_factory.build();
rlnc_decoder::factory decoder_factory(field, max_symbols, max_symbol_size);
auto decoder = decoder_factory.build();
std::vector<uint8_t> payload(encoder->payload_size());
std::vector<uint8_t> block_in(encoder->block_size());
std::generate(block_in.begin(), block_in.end(), rand);
encoder->set_const_symbols(storage::storage(block_in));
std::vector<uint8_t> block_out(decoder->block_size());
decoder->set_mutable_symbols(storage::storage(block_out));
uint32_t encoded_count = 0;
while(!decoder->is_complete()){
uint32_t bytes_used = encoder->write_payload(payload.data());
++encoded_count;
EV << "Bytes used: " << bytes_used << " Encoded count: " << encoded_count << "\n";
payload_packet *Datenpaket= new payload_packet("Datenpaket");
Datenpaket->setBytesArraySize(payload.size());
Datenpaket->setData_inArraySize(block_in.size());
uint8_t checksum = 0;
for(unsigned int i=0; i < payload.size();i++){
Datenpaket->setBytes(i,payload.at(i));
checksum += payload.at(i);
}
for(unsigned int i=0; i < block_in.size();i++){
Datenpaket->setData_in(i,block_in.at(i));
}
EV << "Packet " << encoded_count <<" payload checksum: " << (unsigned int) checksum;
int n = gateSize("out");
for(int i=0;i<n;i++){
payload_packet *temp = Datenpaket->dup();
send(temp,"out",i);
}
delete Datenpaket;
decoder->read_payload(payload.data());
}
}
void Quelle::send_lnc(){
uint32_t max_symbols = 16; //par("max_symbols");
uint32_t max_symbol_size = 1400; //par("max_symbol_size");
// std::vector<uint8_t> testvector = readFile("testfile.txt");
// EV << "File vector size: " << testvector.size() << "\n";
kodocpp::encoder_factory encoder_factory(
kodocpp::codec::full_vector,
kodocpp::field::binary8,
max_symbols,
max_symbol_size);
kodocpp::encoder encoder = encoder_factory.build();
kodocpp::decoder_factory decoder_factory(
kodocpp::codec::full_vector,
kodocpp::field::binary8,
max_symbols,
max_symbol_size);
kodocpp::decoder decoder = decoder_factory.build();
std::vector<uint8_t> data_out(decoder.block_size());
decoder.set_mutable_symbols(data_out.data(), decoder.block_size());
std::vector<uint8_t> payload(encoder.payload_size());
std::vector<uint8_t> data_in(encoder.block_size());
//std::vector<unsigned int> random_data(32);
std::generate(data_in.begin(), data_in.end(), rand);
// for(unsigned int l=0; l < data_in.size(); l++){
// data_in.push_back( (uint8_t) "a");
// }
encoder.set_const_symbols(data_in.data(),encoder.block_size());
//EV <<"Vector checksum: " << calculate_vector_checksum(data_in) << "\n";
uint32_t encoded_count = 0;
while(!decoder.is_complete()){
uint32_t bytes_used = encoder.write_payload(payload.data());
++encoded_count;
EV << "Bytes used: " << bytes_used << "\n";
payload_packet *Datenpaket= new payload_packet("Datenpaket");
Datenpaket->setBytesArraySize(payload.size());
Datenpaket->setData_inArraySize(data_in.size());
uint8_t checksum = 0;
for(unsigned int i=0; i < payload.size();i++){
Datenpaket->setBytes(i,payload.at(i));
checksum += payload.at(i);
}
for(unsigned int i=0; i < data_in.size();i++){
Datenpaket->setData_in(i,data_in.at(i));
}
EV << "Packet " << encoded_count <<" payload checksum: " << (unsigned int) checksum;
int n = gateSize("out");
for(int i=0;i<n;i++){
payload_packet *temp = Datenpaket->dup();
send(temp,"out",i);
}
delete Datenpaket;
decoder.read_payload(payload.data());
}
EV << "Ecoded " << encoded_count << " packets!" << "\n";
}
void Quelle::initialize(){
//cMessage *msg = new cMessage("Testmessage");
uint32_t max_symbols = 16; //par("max_symbols");
uint32_t max_symbol_size = 1400; //par("max_symbol_size");
is_rlnc = par("is_rlnc");
EV << "RLNC: " << is_rlnc << "\n";
// std::vector<uint8_t> testvector = readFile("testfile.txt");
// EV << "File vector size: " << testvector.size() << "\n";
kodocpp::encoder_factory encoder_factory(
kodocpp::codec::full_vector,
kodocpp::field::binary8,
max_symbols,
max_symbol_size);
kodocpp::encoder encoder = encoder_factory.build();
kodocpp::decoder_factory decoder_factory(
kodocpp::codec::full_vector,
kodocpp::field::binary8,
max_symbols,
max_symbol_size);
kodocpp::decoder decoder = decoder_factory.build();
std::vector<uint8_t> data_out(decoder.block_size());
decoder.set_mutable_symbols(data_out.data(), decoder.block_size());
std::vector<uint8_t> payload(encoder.payload_size());
std::vector<uint8_t> data_in(encoder.block_size());
//std::vector<unsigned int> random_data(32);
std::generate(data_in.begin(), data_in.end(), rand);
// for(unsigned int l=0; l < data_in.size(); l++){
// data_in.push_back( (uint8_t) "a");
// }
encoder.set_const_symbols(data_in.data(),encoder.block_size());
//EV <<"Vector checksum: " << calculate_vector_checksum(data_in) << "\n";
uint32_t encoded_count = 0;
while(!decoder.is_complete()){
uint32_t bytes_used = encoder.write_payload(payload.data());
++encoded_count;
EV << "Bytes used: " << bytes_used << "\n";
payload_packet *Datenpaket= new payload_packet("Datenpaket");
Datenpaket->setBytesArraySize(payload.size());
Datenpaket->setData_inArraySize(data_in.size());
uint8_t checksum = 0;
for(unsigned int i=0; i < payload.size();i++){
Datenpaket->setBytes(i,payload.at(i));
checksum += payload.at(i);
}
for(unsigned int i=0; i < data_in.size();i++){
Datenpaket->setData_in(i,data_in.at(i));
}
EV << "Packet " << encoded_count <<" payload checksum: " << (unsigned int) checksum;
int n = gateSize("out");
for(int i=0;i<n;i++){
payload_packet *temp = Datenpaket->dup();
send(temp,"out",i);
}
delete Datenpaket;
decoder.read_payload(payload.data());
}
EV << "Ecoded " << encoded_count << " packets!" << "\n";
// std::vector<unsigned int> converted_values;
//
// for(unsigned int i=0; i < data_in.size(); i++){
// unsigned int temp = 0;
//
// EV << "data_in Stelle " << i << ": " << (unsigned int) data_in[i] <<"\n";
//
// temp = (unsigned int) data_in[i];//(data_in[i] << 8) | data_in[1];
//
// EV << "Temp Stelle " << i << ": " << temp << "\n";
// converted_values.push_back(temp);
// }
//
// EV <<"Vector checksum: " << calculate_vector_checksum(converted_values) << "\n";
//
// payload_packet *testpacket = new payload_packet("Testpaket");
// testpacket->setBytesArraySize(data_in.size());
//
// for(unsigned int i=0; i< data_in.size();i++){
// testpacket->setBytes(i,data_in[i]);
// }
//
// testpacket->setDaten(converted_values);
//
// EV << "Generated a message";
// int n = gateSize("out");
// for(int i=0;i<n;i++){
// payload_packet *temp = testpacket->dup();
// send(temp,"out",i);
// }
//delete testpacket;
}
void Quelle::handleMessage(cMessage *msg){
//EV << "Received a message! Something is gone wrong!";
}我确信,您在将std::vector<uint8_t> payload放入payload_paket *Datenpaket中时,已经意识到了它的可怕处理。由于某种原因,Omnet++数据包定义无法处理预定义的std::vector<uin8t_t>,因此我不得不为此声明一个数组,并将payload的内容复制到bytes数组中。但这对我的问题不重要。
是否有人知道我的代码出了什么问题,或者能给我一个提示,说明这可能不是我的错?
我很感激在这方面的任何帮助!
提前感谢!
编辑#1:
我使用Makefile来使用链接的静态库和共享库进行编译。顺序结构可以描述为:sim_folder/libs/ many_libs_in_subdirectories和sim_folder/include/ many includes in subdirectories。我的Makefile看起来如下:
#
# OMNeT++/OMNEST Makefile for simulation
#
# This file was generated with the command:
# opp_makemake -f -I./include -l libkodoc.so
#
# Name of target to be created (-o option)
TARGET = simulation$(EXE_SUFFIX)
# User interface (uncomment one) (-u option)
USERIF_LIBS = $(ALL_ENV_LIBS) # that is, $(TKENV_LIBS) $(QTENV_LIBS) $(CMDENV_LIBS)
#USERIF_LIBS = $(CMDENV_LIBS)
#USERIF_LIBS = $(TKENV_LIBS)
#USERIF_LIBS = $(QTENV_LIBS)
# C++ include paths (with -I)
INCLUDE_PATH = -I./include -I../Omnetpp/omnetpp-5.1pre2/include/omnetpp -I./include/kodo-rlnc #-I./include/platform -I./include/sak -I./include/kodo_core -I./include/fifi -I./include/storage -I./include/boost -I./include/endian -I./include/hex
# Additional object and library files to link with
EXTRA_OBJS =
# Additional libraries (-L, -l options)
#LIBS = libkodoc.so
LIBS = libkodoc.so \
./libs/fifi/libfifi.a \
./libs/cpuid/src/cpuid/libcpuid.a \
./libs/gtest/libgtest.a \
./libs/sak/libsak.a \
./libs/boost/libboost_chrono.a \
./libs/boost/libboost_filesystem.a \
./libs/boost/libboost_iostreams.a \
./libs/boost/libboost_program_options.a \
./libs/boost/libboost_system.a \
./libs/boost/libboost_timer.a \
./libs/boost/libboost_thread.a \
./libs/gauge/src/gauge/libgauge.a \
./libs/tables/src/tables/libtables.a
#-L./libs/allocate -L./libs/cpuid -L./libs/fifi/ -L./libs/gtest -L./libs/kodo-core -L./libs/sak -L./libs/stub -L./libs/boost -L./libs/endian -L./libs/gauge -L./libs/hex -L./libs/platform -L./libs/storage -L./libs/tables
# Output directory
PROJECT_OUTPUT_DIR = out
PROJECTRELATIVE_PATH =
O = $(PROJECT_OUTPUT_DIR)/$(CONFIGNAME)/$(PROJECTRELATIVE_PATH)
# Object files for local .cc, .msg and .sm files
OBJS = \
$O/eve.o \
$O/Quelle.o \
$O/Router.o \
$O/Senke.o \
$O/txc1.o \
$O/nc_packet_m.o \
$O/payload_packet_m.o
# Message files
MSGFILES = \
nc_packet.msg \
payload_packet.msg
# SM files
SMFILES =
#------------------------------------------------------------------------------
# Pull in OMNeT++ configuration (Makefile.inc)
ifneq ("$(OMNETPP_CONFIGFILE)","")
CONFIGFILE = $(OMNETPP_CONFIGFILE)
else
ifneq ("$(OMNETPP_ROOT)","")
CONFIGFILE = $(OMNETPP_ROOT)/Makefile.inc
else
CONFIGFILE = $(shell opp_configfilepath)
endif
endif
ifeq ("$(wildcard $(CONFIGFILE))","")
$(error Config file '$(CONFIGFILE)' does not exist -- add the OMNeT++ bin directory to the path so that opp_configfilepath can be found, or set the OMNETPP_CONFIGFILE variable to point to Makefile.inc)
endif
include $(CONFIGFILE)
# Simulation kernel and user interface libraries
OMNETPP_LIBS = $(OPPMAIN_LIB) $(USERIF_LIBS) $(KERNEL_LIBS) $(SYS_LIBS)
COPTS = $(CFLAGS) $(IMPORT_DEFINES) $(INCLUDE_PATH) -I$(OMNETPP_INCL_DIR)
MSGCOPTS = $(INCLUDE_PATH)
SMCOPTS =
# we want to recompile everything if COPTS changes,
# so we store COPTS into $COPTS_FILE and have object
# files depend on it (except when "make depend" was called)
COPTS_FILE = $O/.last-copts
ifneq ("$(COPTS)","$(shell cat $(COPTS_FILE) 2>/dev/null || echo '')")
$(shell $(MKPATH) "$O" && echo "$(COPTS)" >$(COPTS_FILE))
endif
#------------------------------------------------------------------------------
# User-supplied makefile fragment(s)
# >>>
# <<<
#------------------------------------------------------------------------------
# Main target
all: $O/$(TARGET)
$(Q)$(LN) $O/$(TARGET) .
$O/$(TARGET): $(OBJS) $(wildcard $(EXTRA_OBJS)) Makefile $(CONFIGFILE)
@$(MKPATH) $O
@echo Creating executable: $@
$(Q)$(CXX) $(LDFLAGS) -o $O/$(TARGET) $(OBJS) $(EXTRA_OBJS) $(AS_NEEDED_OFF) $(WHOLE_ARCHIVE_ON) $(LIBS) $(WHOLE_ARCHIVE_OFF) $(OMNETPP_LIBS)
.PHONY: all clean cleanall depend msgheaders smheaders
.SUFFIXES: .cc
$O/%.o: %.cc $(COPTS_FILE) | msgheaders smheaders
@$(MKPATH) $(dir $@)
$(qecho) "$<"
$(Q)$(CXX) -c $(CXXFLAGS) $(COPTS) -o $@ $<
%_m.cc %_m.h: %.msg
$(qecho) MSGC: $<
$(Q)$(MSGC) -s _m.cc $(MSGCOPTS) $?
%_sm.cc %_sm.h: %.sm
$(qecho) SMC: $<
$(Q)$(SMC) -c++ -suffix cc $(SMCOPTS) $?
msgheaders: $(MSGFILES:.msg=_m.h)
smheaders: $(SMFILES:.sm=_sm.h)
clean:
$(qecho) Cleaning...
$(Q)-rm -rf $O
$(Q)-rm -f simulation simulation.exe libsimulation.so libsimulation.a libsimulation.dll libsimulation.dylib
$(Q)-rm -f ./*_m.cc ./*_m.h ./*_sm.cc ./*_sm.h
cleanall: clean
$(Q)-rm -rf $(PROJECT_OUTPUT_DIR)
# include all dependencies
-include $(OBJS:%.o=%.d)如您所见,我的项目中包含了几个文件(eve.cc、Router.cc、Quelle.cc .)。但唯一包括kodo-rlnc的类是我之前发布的Quelle.cc。
还是谢谢你的帮助!
编辑#2
我设法通过一种快速而肮脏的方法修复了多个定义错误:我强迫once.cpp不包含该once.cpp这实际上不是一个一般性的解决办法,但它可能足以满足我的目的。但是,由于我不知道哪个库可能也需要once_atomic.cpp的功能,未来的验证是不可预测的。
现在,我仍在未定义的引用-issue中工作。
编辑#3
今天早上,我想出了如何用未定义的引用来解决这个问题。首先,我需要在链接libgtest.a时声明一个附加选项。正确的形式不是./libs/gtest/libgtest.a,而是./libs/gtest/libgtest.a -pthread。但这并没有解决整个问题:作为一个使用gcc的新手,我忘了检查链接顺序。按照这个问题中的提示,我使用-Wl,--start-group -la -lb -lc -Wl,--end-group在链接库中启用了一个循环组。
因此,随着第一个问题的脏-固定和第二个问题通常固定,我的项目开始工作。
对我来说,现在的主题是closed。
但是,有没有人可以告诉我,如何以一种明确的正常方式解决第一个问题?最好不要依赖肮脏的解决方案。
谢谢!
发布于 2017-12-14 15:07:47
正如在编辑部分中所写的,我的问题被一个快速而肮脏的解决方案解决了。它似乎一直在运作,希望将来也是如此。
要修复once.cpp和once_atomic.cpp中的多重定义,只需在boost::once_atomic.cpp的once.cpp中注释once_atomic.cpp的包含。
//#include "./once_atomic.cpp"要解决第二个问题,在gtest::p线程中使用未定义的符号引用,只需要Makefile中的两个简单条目:
在LIBS中,另外声明:./libs/gtest/libgtest.a -pthread,并在LIBS周围的编译语句中添加一个循环组:
$(Q)$(CXX) $(LDFLAGS) -o $O/$(TARGET) $(OBJS) $(EXTRA_OBJS) $(AS_NEEDED_OFF) $(WHOLE_ARCHIVE_ON) -Wl,--start-group $(LIBS) -Wl,--eng-group $(WHOLE_ARCHIVE_OFF) $(OMNETPP_LIBS)这是为我做的。但也许有人能告诉我一个更好、更顺畅的解决方案!
提前感谢!
https://stackoverflow.com/questions/47793346
复制相似问题