C++: undefined reference to `xxx`

53 Views Asked by At

I have a project, and the directory structure is:

.
├── bin
├── README.md
├── src
│   ├── blocking_deque
│   │   └── blocking_deque.hpp
│   ├── buffer
│   │   ├── buffer.cpp
│   │   └── buffer.h
│   ├── epoller
│   │   ├── epoller.cpp
│   │   └── epoller.h
│   └── log
│       ├── log.cpp
│       └── log.h
└── test
    ├── Makefile
    └── test_log.cpp

log.h:

#ifndef LOG_H
#define LOG_H

#include <memory>
#include <string>
#include <thread>
#include <mutex>
#include "../blocking_deque/blocking_deque.hpp"
#include "../buffer/buffer.h"

class Log {
public:
    // ...
    bool is_open();
    // ...
private:
    Log();
    virtual ~Log();

    // ...
    Buffer buf;
    // ...
};

#endif // LOG_H

log.cpp:

#include <cstdio>
#include <ctime>
#include <cstring>
#include <cassert>
#include <cstdarg>
#include <sys/stat.h>
#include <sys/time.h>
#include "log.h"

Log::Log() {
// ...
}

Log::~Log() {
// ...
}

inline bool Log::is_open() {
// ...
}

buffer.h:

#ifndef BUFFER_H
#define BUFFER_H

#include <vector>
#include <string>
#include <atomic>

class Buffer {
// ...
};

#endif // BUFFER_H

buffer.cpp:

#include <sys/uio.h>  // readv
#include <unistd.h>   // write
#include <cerrno>     // errno
#include <cassert>    // assert
#include <algorithm>  // copy
#include "buffer.h"

// ... definition of some members of Buffer

blocking_deque.hpp:

#ifndef BLOCKING_DEQUE_HPP
#define BLOCKING_DEQUE_HPP

#include <deque>
#include <condition_variable>
#include <mutex>

template <typename T>
class BlockingDeque {
// ...
};

// ... definition of some members

test_log.cpp:

#include "../src/log/log.h"


void test_log() {
    using level_type = Log::level_type;
    Log::get_instance()->init(1, "./test_log1", ".log", 0);
    int cnt = 0;
    for (level_type lv=3; lv>=0; --lv) {
        Log::get_instance()->set_level(lv);
        for (int i=0; i<10000; ++i) {
            for (level_type new_lv=0; new_lv<=3; ++new_lv) {
                LOG_BASE(new_lv, "%s ===== %d", "test", cnt++);
            }
        }
    }
    Log::get_instance()->init(1, "./test_log2", ".log", 5000);
    cnt = 0;
    for (level_type lv=0; lv<=3; ++lv) {
        Log::get_instance()->set_level(lv);
        for (int i=0; i<10000; ++i) {
            for (level_type new_lv=3; new_lv>=0; --new_lv) {
                LOG_BASE(new_lv, "%s ==== %d", "test", cnt++);
            }
        }
    }
}

int main() {
    test_log();
}

When I use g++ -g test/test_log.cpp src/blocking_deque/blocking_deque.hpp src/buffer/buffer.cpp src/log/log.cpp -o ./a, the compiler(specifically, it's the linker) informs me that undefined reference to some function. The detail is shown below:

/usr/bin/ld: /tmp/cc3lAVRd.o: in function `test_log()':
/home/fansuregrin/workshop/my_http_server/test/test_log.cpp:18: undefined reference to `Log::is_open()'
/usr/bin/ld: /home/fansuregrin/workshop/my_http_server/test/test_log.cpp:28: undefined reference to `Log::is_open()'
/usr/bin/ld: /tmp/ccnM4HDs.o: in function `Log::write(int, char const*, ...)':
/home/fansuregrin/workshop/my_http_server/src/log/log.cpp:167: undefined reference to `Buffer::has_written(unsigned long)'
collect2: error: ld returned 1 exit status

However, the Log::is_open() is defined in src/log/log.cpp, the Buffer::has_written(unsigned long) is defined in src/buffer/buffer.cpp. Why it can't be compiled?

==============================

The reason for the problem is inline! After I removed the inlines affixed to Log::is_open and Buffer::has_written, then there is no error.

0

There are 0 best solutions below