神秘的链接器错误
Posted
技术标签:
【中文标题】神秘的链接器错误【英文标题】:mysterious linker error 【发布时间】:2011-06-06 15:21:01 【问题描述】:我编写了一个使用一些类和 procol 缓冲区的简单程序。这些类是为了使计算机之间的连接和发送消息更容易。编译成功。但是,链接器说:
server.o:在函数“main”中:
server.cpp:(.text+0x24): 未定义 参考 `dataExchange::Server::Server(无符号 int)'
server.cpp:(.text+0x39): 未定义的引用 `dataExchange::Server::accept()'
server.cpp:(.text+0x51): 未定义 参考 `dataExchange::Connection::receive()' collect2: ld 返回 1 个退出状态
代码: 服务器.cpp:
#include <iostream>
#include "connection.h"
#include "protocol.pb.h"
using namespace std;
using namespace msg;
using namespace dataExchange;
int main()
Server server(1234);
while(1)
Connection con = server.accept();
Annoucement ann = con.receive();
cout << ann.typ() << endl;
连接.h:
namespace dataExchange
class SocketMaintenance
protected:
sockaddr_in addr;
int s;
public:
SocketMaintenance(const unsigned int) throw();
SocketMaintenance(const sockaddr_in, const int) throw();
SocketMaintenance(const SocketMaintenance&) throw();
~SocketMaintenance();
void write(const char*, const int);
;
class Connection
FileOutputStream* raw_output;
FileInputStream* raw_input;
char buffer[1024];
public:
Connection(const char*, const unsigned int);// throw(WrongAddress);
Connection(const SocketMaintenance&);//throw(ConnectFailed);
void send(const Message&) throw();
Annoucement receive() throw();
;
class Server
public:
Server(const unsigned int);// throw(BindFailed,ListenFailed);
Connection accept() throw();
;
链接器失败的原因是什么?
建造过程:
g++ server.cpp -c; g++ 协议.pb.cc -c; g++ 连接.cpp -c; g++ server.o protocol.pb.o connection.o -lprotobuf
连接.cpp
using namespace std;
using namespace msg;
using namespace google::protobuf;
using namespace google::protobuf::io;
namespace dataExchange
class SocketMaintenance
protected:
sockaddr_in addr;
int s;
public:
SocketMaintenance(const unsigned int port)
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
s = socket(AF_INET, SOCK_STREAM, 0);
SocketMaintenance(const sockaddr_in Addr, const int Socket)
addr = Addr;
s = Socket;
SocketMaintenance(const SocketMaintenance& source)
addr = source.addr;
s = source.s;
~SocketMaintenance()
close(s);
void write(const char* buffer, const int n)
::write(s, buffer, n);
;
class Connection : public SocketMaintenance
FileOutputStream* raw_output;
FileInputStream* raw_input;
char buffer[1024];
public:
Connection(const char* IP, const unsigned int port) : SocketMaintenance(port)
if(inet_pton(AF_INET, IP, &addr.sin_addr)<=0)
throw WrongAddress();
if(connect(s, (sockaddr*)&addr, sizeof(addr))<0)
throw ConnectFailed();
raw_output = new FileOutputStream(s);
raw_input = new FileInputStream(s);
Connection(const SocketMaintenance& source) : SocketMaintenance(source)
~Connection()
delete raw_output;
void send(const Message& msg) throw(EmptyMessage)
CodedOutputStream* coded_output = new CodedOutputStream(raw_output);
int n = msg.ByteSize();
if(n<=0) throw EmptyMessage();
coded_output->WriteVarint32(n);
delete coded_output;
raw_output->Flush();
msg.SerializeToArray(buffer, n);
SocketMaintenance::write(buffer, n);
Annoucement receive() throw()
CodedInputStream* coded_input = new CodedInputStream(raw_input);
google::protobuf::uint32 n;
coded_input->ReadVarint32(&n);
char *b;
int m;
coded_input->GetDirectBufferPointer((const void**)&b, &m);
Annoucement ann;
ann.ParseFromArray(b, n);
return ann;
;
class Server : public SocketMaintenance
public:
Server(const unsigned int port) : SocketMaintenance(port)
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(s, (struct sockaddr *)&addr, sizeof(addr))<0)
throw BindFailed();
if(listen(s, 5)<0)
throw ListenFailed();
Connection accept() throw()
sockaddr_in client;
socklen_t client_len;
int client_socket = ::accept(s, (sockaddr*)&client, &client_len);
return Connection(SocketMaintenance(client, client_socket));
;
【问题讨论】:
请发布您正在使用的链接器(不是liker!)命令。 【参考方案1】:很可能忘记编译和/或链接"connection.cpp"
。我至少希望你有这样一个文件,它实现了所有的功能?
我认为您对 .h 和 .cpp 的拆分方式有一些基本的误解。在 .cpp 中,您不必简单地重新声明类,这一次是在其中定义的函数。你需要这样做:
// connection.cpp
namespace dataExchange
// define the constructor of Server
Server::Server(const unsigned int port)
: SocketMaintenance(port)
// ....
// define the accept function of Server
Connection accept() throw()
// ...
// ...
但这只是问题的一部分,看来你需要得到a good C++ book。例如,您需要在声明类的标头中进行任何继承。
【讨论】:
我有。我确实构建了目标文件。如果这很简单,我会猜测自己!我做:g++ server.cpp -c; g++ 协议.pb.cc -c; g++ 连接.cpp -c; g++ server.o protocol.pb.o connection.o -lprotobuf。当我将所有内容合并到一个文件中时,它可以工作。我现在就是这样测试的。 @lord:你也链接了吗? g++ server.o protocol.pb.o connection.o -lprotobuf @lord:奇怪,你能不能把 .cpp 中的 Server 构造函数的定义编辑到你的问题中并通知我更新? @Xeo:+1 表示“你需要一本好的 C++ 书”。 @lord:您需要重做您的 connection.cpp 文件。这是错误的。【参考方案2】:当您#include "connection.h"
时,您将获得Server
的方法的声明。这基本上告诉编译器存在哪些方法,并使编译成功。
为了链接您的可执行文件,您需要链接这些方法的定义(即实现它们的实际代码)。对于connection.h
中定义的类,它们通常驻留在名为connection.cpp
或类似名称的文件中。您需要编译该文件,并在链接步骤中指定生成的目标文件。
【讨论】:
【参考方案3】:您的项目中应该有一个实现构造函数Server::Server(const unsigned int)
的connection.cpp。你有吗?
您也可以自行粘贴您发出的命令进行编译,您可能会缺少链接文件。
【讨论】:
以上是关于神秘的链接器错误的主要内容,如果未能解决你的问题,请参考以下文章