首页 > 解决方案 > 对已实现函数的未定义引用

问题描述

我正在使用一类带有头文件和 cpp 文件的线程。当我把它们都放在空的测试文件中时,它会写:

g++ -g -pedantic -ansi -Wall -Werror -std=c++03 -I../include  -c -o test.o test.cpp
g++ -g  test.o thread.o   -o test
thread.o: In function `Thread::~Thread()':
/home/tomer/work/mt/hash2/cpp/thread.cpp:15: undefined reference to `pthread_detach'
thread.o: In function `Thread::start()':
/home/tomer/work/mt/hash2/cpp/thread.cpp:40: undefined reference to `pthread_create'
thread.o: In function `Thread::join()':
/home/tomer/work/mt/hash2/cpp/thread.cpp:49: undefined reference to `pthread_join'
thread.o: In function `Thread::cancel()':
/home/tomer/work/mt/hash2/cpp/thread.cpp:58: undefined reference to `pthread_cancel'
thread.o: In function `Thread::detach()':
/home/tomer/work/mt/hash2/cpp/thread.cpp:66: undefined reference to `pthread_detach'
collect2: error: ld returned 1 exit status
<builtin>: recipe for target 'test' failed
make: *** [test] Error 1

我只是试图编译 Thread.h 和 Thread.cpp

//Thread.h looks like this:
#ifndef THREAD_H
#define THREAD_H

#include <cstddef>
#include <pthread.h>
#include <string>

class Thread
{
public:
    Thread(size_t a_userID = 0);
    virtual ~Thread();

    bool start();
    void join();
    void cancel();
    void detach();


private:
    static void* threadMainFunction(void *);
    virtual void run() = 0;
    bool isAlive(std::string a_msg);

private:
    bool m_joinable;

protected:
    pthread_t m_threadID;
    size_t m_userID;
};

#endif

//Thread.cpp looks like this:
#include <exception>
#include "Thread.h"
#include <iostream>
Thread::Thread(size_t a_userID)
: m_joinable(true)
, m_threadID(0)
, m_userID(a_userID)
{
}

Thread::~Thread()
{
    if(m_joinable)
    {
        pthread_detach(m_threadID);
    }
}

void* Thread::threadMainFunction(void *a_thread)
{
    Thread* thread = reinterpret_cast<Thread*>(a_thread);
    try
    {
        thread->run();
    }
    catch(const std::exception& e)
    {
        std::cout<<"what exepction\n";
        std::cerr << e.what() << '\n';
    }
    catch(...)
    {
        throw;
    }
    return 0;
}

bool Thread::start()
{
    int r = pthread_create(&m_threadID, 0, threadMainFunction, this);
    return r == 0;
}

void Thread::join()
{
    if(isAlive("Thread::join on thread not started"))
    {
        void *status;
        pthread_join(m_threadID, &status);
        m_joinable = false;
    }
}

void Thread::cancel()
{
    if(isAlive("Thread::cancel on thread not started"))
    {
        pthread_cancel(m_threadID);
    }
}

void Thread::detach()
{
    if(isAlive("Thread::detach on thread not started"))
    {
        pthread_detach(m_threadID);
    }
}

bool Thread::isAlive(std::string a_msg)
{
    if(m_threadID == 0)
    {
        throw(std::runtime_error(a_msg));
        return false;
    }
    return true;
}

标签: c++

解决方案


您在这里面临的问题不是构建问题,而是链接问题。在构建thread.o时,编译器知道pthread_create存在并在某处定义,因为在pthread.h标头中声明。

如果您曾经nm查看 中使用的符号thread.o,您会看到类似于以下内容:

U _pthread_create
U _pthread_detach
...

这告诉您thread.o引用了多个未定义的符号,包括pthread_create. 换句话说,此时的机器代码pthread_create是未知的。在您需要将目标文件链接到可执行文件(这是链接器的角色)之前,这非常好。

在这个阶段,您必须告诉链接器在哪里可以找到这些未定义的符号,可能来自另一个目标文件或静态/共享库。因为pthread,这些符号是在 中定义的libpthread,您很可能在系统目录中找到libpthread.a. 您可以g++通过添加来告诉链接此库-lpthread(请注意,使用时省略了libfrom ):libpthread-l

g++ -g test.o thread.o -o test -lpthread

通常,如果您使用目录中lib${LIBNAME}.a可用的静态库中引用的符号${LIBDIR},您可以告诉链接器将其用于:

g++ -g *.o -L$LIBDIR -l${LIBNAME}

推荐阅读