簡體   English   中英

C ++對庫函數的未定義引用

[英]C++ undefined reference to library functions

我有一個正在建立的“小型”圖形庫,在嘗試建立一個與之鏈接的測試二進制文件時遇到了這個錯誤:

al_test.o: In function `test_wave()':
al_test.cpp:(.text+0x1a7): undefined reference to `min::wave::wave(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
...

(以及其他類似的錯誤,但我們將重點關注這一問題)。 該庫是在具有以下規則的makefile中構建的:

all: libmgl.a libmgl.so

libmgl.so: $(OBJECTS)
    $(LD) $* $(LDFLAGS) -shared -o $@

libmgl.a: $(OBJECTS)
    $(AR) $(ARFLAGS) libmgl.a $^

%.o: %.cpp
    $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) -c -o $@ $<

CXXFLAGS包含一些內容,但最重要的是-std=c++14 -O3 -Wall -Werror ,所有對象都可以正常編譯,並且靜態和動態庫的輸出沒有錯誤或警告。

現在,我有一個文件source/test/al_test.cpp該文件用於測試庫中看起來像這樣的音頻部分:

#include <iostream>
#include "twave.h"
int main()
{
    try
    {
        bool out = true;
        out = out && test_wave();
        // out = out && test_ogg();
        // out = out && test_sound_buffer();
        if (out)
        {
            std::cout << "Sound tests passed!" << std::endl;
            return 0;
        }
    }
    catch (std::exception &ex)
    {
        std::cout << ex.what() << std::endl;
    }

    std::cout << "Sound tests failed!" << std::endl;
    return -1;
}

並在test_wave中定義了twave.h函數,如下所示:

#include <stdexcept>
#include "min/wave.h"
bool test_wave()
{
    bool out = true;

    // Load invention wav file
    {
        const min::wave sound = min::wave("data/sound/invention_no_1.wav");

        // File should not be mono
        out = out && !sound.is_mono();
        if (!out)
        {
            throw std::runtime_error("Failed wave file not is_mono");
        }

        // Other checks that aren't important...
    }

    return out;
}

所以這是我的問題: min::wave::wave()確實存在,並且應該在庫中。 這是簡化的min/wave.h

#ifndef __WAVE__
#define __WAVE__
#include <string>
namespace min {
class wave
{
  private:
    void load(const std::string);
  public:
    wave(const std::string&);
};
}
#endif

min/wave.cpp

#include "wave.h"

min::wave::wave(const std::string &file)
{
    load(file);
}

// Definition of `load` omitted; I don't think it's important,
// but know that it is here

因此該文件存在,函數聲明和定義都存在,並且在我的make輸出中可以看到wave.o已被構建並鏈接/歸檔到libmgl.a / libmgl.so 但是編譯器聲稱它不存在。 似乎不是鏈接順序問題; 這是我構建測試的過程:

g++ -c -Imin/ al_test.cpp -o al_test.o
g++ al_test.o -L. -lmgl -lX11 -lGL -lfreetype -lopenal -lvorbisfile -o bin/al_test

mgl顯然是我的庫的名稱,而這正是它依賴的其他內容。 我也嘗試替換-L. 使用-L/absolute/path/to/project/directory/ ,無濟於事。

為什么g ++認為我的函數未定義?

nm命令

根據普遍的需求,以下是一些nm命令及其輸出:

靜態庫:

nm -C libmgl.a | grep wave
wavefront.o
wave.o:
0000000000000090 T min::wave::load(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)
0000000000000000 W void min::wave::load<min::mem_file>(min::mem_file const&)
0000000000000000 W void min::wave::load<std::vector<unsigned char, std::allocator<unsigned char> > >(std::vector<unsigned char, std::allocator<unsigned char> > const&)
0000000000000000 T min::wave::clear()
0000000000000880 T min::wave::wave(min::mem_file const&)
0000000000000720 T min::wave::wave(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
0000000000000880 T min::wave::wave(min::mem_file const&)
0000000000000720 T min::wave::wave(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
0000000000000080 T min::wave::get_sample_rate() const
0000000000000060 T min::wave::get_data_samples() const
0000000000000050 T min::wave::get_bits_per_sample() const
0000000000000040 T min::wave::data() const
0000000000000020 T min::wave::is_mono() const
0000000000000030 T min::wave::is_stereo() const
0000000000000550 T min::sound_buffer::add_wave_pcm(min::wave const&)
                 U min::wave::get_sample_rate() const
                 U min::wave::get_bits_per_sample() const
                 U min::wave::data() const
                 U min::wave::is_stereo() const

...動態庫:

nm -C libmgl.so
0000000000201020 B __bss_start
0000000000201020 b completed.7631
                 w __cxa_finalize
0000000000000460 t deregister_tm_clones
00000000000004f0 t __do_global_dtors_aux
0000000000200e88 t __do_global_dtors_aux_fini_array_entry
0000000000201018 d __dso_handle
0000000000200e90 d _DYNAMIC
0000000000201020 D _edata
0000000000201028 B _end
000000000000053c T _fini
0000000000000530 t frame_dummy
0000000000200e80 t __frame_dummy_init_array_entry
0000000000000548 r __FRAME_END__
0000000000201000 d _GLOBAL_OFFSET_TABLE_
                 w __gmon_start__
0000000000000420 T _init
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
00000000000004a0 t register_tm_clones
0000000000201020 d __TMC_END__

...以及測試文件:

nm -C al_test.o
                 U __cxa_allocate_exception
                 U __cxa_atexit
                 U __cxa_begin_catch
                 U __cxa_end_catch
                 U __cxa_free_exception
                 U __cxa_throw
                 U __dso_handle
00000000000000e0 t _GLOBAL__sub_I__Z9test_wavev
                 U __gxx_personality_v0
0000000000000000 r .LC1
0000000000000000 T main
                 U __stack_chk_fail
                 U _Unwind_Resume
0000000000000000 T test_wave()
                 U operator delete(void*)
                 U min::wave::wave(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
                 U min::wave::is_mono() const
                 U std::runtime_error::runtime_error(char const*)
                 U std::runtime_error::~runtime_error()
                 U std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_create(unsigned long&, unsigned long)
                 U std::ios_base::Init::Init()
                 U std::ios_base::Init::~Init()
                 U std::basic_ios<char, std::char_traits<char> >::clear(std::_Ios_Iostate)
                 U std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
                 U std::cout
                 U std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)
0000000000000000 b std::__ioinit
                 U typeinfo for std::runtime_error
                 U typeinfo for std::exception

有了有關靜態和動態庫中可用符號的更多信息,我得出結論,共享庫為空。

它是空的,因為這里的$*擴展為空。

 libmgl.so: $(OBJECTS) $(LD) $* $(LDFLAGS) -shared -o $@ 

請參閱GNU make文檔

如果顯式規則中的目標名稱未以可識別的后綴結尾,則將'$ *'設置為該規則的空字符串。

$^代替$*就像用來構建libmgl.a一樣,應該可以解決您的問題。

由於nm libmgl.so | grep wave nm libmgl.so | grep wave返回任何內容(請參閱注釋),至少我們知道該庫未正確鏈接(構建?)。

確實,您應該調用g++進行鏈接:

$(CXX) $* $(LDFLAGS) -shared -o $@

完成此操作后,由UKUKkey用戶建議:

關聯事項的順序

因此,您的二進制文件應這樣構建:

g++ -L. -lmgl -lX11 -lGL -lfreetype -lopenal -lvorbisfile -o bin/al_test al_test.o

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM