2

在一个项目中,我noinst_PROGRAM定义了两个 's。其中一个工作得很好,但另一个给我以下信息:

/home/altern8/workspaces/4355/libgdata/test/.libs/lt-gdatacalendar:符号查找错误:/home/altern8/workspaces/4355/libgdata/test/.libs/lt-gdatacalendar:未定义符号:_ZN5gdata7service7ServiceD1Ev

我一直在查看我的 Makefile.am 文件,但找不到任何我错过的东西。该应用程序编译正确,所以我猜这意味着正确找到了头文件,但由于某种原因我gdata::service::Service没有包含在 src/libgdata.la 库中。

我的假设可能是正确的吗?src/libgdata.la 库中定义的其他类似乎可用。“make”的输出表明 Service.cc 文件正在正确编译......我应该在哪里确定它是否包含在最终库中的任何指针?

编辑:

根据迄今为止提供的答案,我已经能够进一步调试它。

析构函数在 Service.cc 中定义。如果我在头文件中给析构函数一个主体,一切都会正常工作。

// In Service.h
~Service() {}

// In Service.cc
// Service::~Service() {}

现在析构函数“工作”了,我遇到了在 Service.cc 中定义的其他方法,但没有找到。

使用@ephemient 的方法,在我看来这些符号实际上已包含在库中。还是我错误地读取了输出?

000000e0 T _ZN55gdata7service7Service22addCommonRequestHeaderERKSsS4_
000000a0 T _ZN55gdata7service7Service22addCommonRequestHeaderERKSsS4_b
./src/.libs/libgdata.a
000240d0 T _ZN55gdata7service7Service22addCommonRequestHeaderERKSsS4_
00024090 T _ZN55gdata7service7Service22addCommonRequestHeaderERKSsS4_b
000240d0 T _ZN55gdata7service7Service22addCommonRequestHeaderERKSsS4_
00024090 T _ZN55gdata7service7Service22addCommonRequestHeaderERKSsS4_b
./src/.libs/libgdata.so
00000080 T _ZN55gdata7service7Service22addCommonRequestHeaderERKSsS4_
00000070 T _ZN55gdata7service7Service22addCommonRequestHeaderERKSsS4_b
./src//gdata/service/libgdata__gdata_service_la-Service.o
000000e0 T _ZN55gdata7service7Service22addCommonRequestHeaderERKSsS4_
000000a0 T _ZN55gdata7service7Service22addCommonRequestHeaderERKSsS4_b
./src//gdata/service/.libs/libgdata__gdata_service.a
000000e0 T _ZN55gdata7service7Service22addCommonRequestHeaderERKSsS4_
000000a0 T _ZN55gdata7service7Service22addCommonRequestHeaderERKSsS4_b
./src//gdata/service/.libs/libgdata__gdata_service_la-Service.o

我的 src/Makefile.am 看起来像这样:

SUBDIRS = gdata

lib_LTLIBRARIES = libgdata.la

libgdata_la_SOURCES = 

libgdata_la_LIBADD = \
    gdata/client/libgdata_gdata_client.la \
    gdata/data/libgdata_gdata_data.la \
    gdata/data/youtube/libgdata_gdata_data_youtube.la \
    gdata/util/libgdata_gdata_util.la \
    gdata/service/libgdata_gdata_service.la \
    gdata/service/calendar/libgdata_gdata_service_calendar.la

我的 src/gdata/service/Makefile.am 看起来像这样:

SUBDIRS = calendar

noinst_LTLIBRARIES = libgdata_gdata_service.la

libgdata_gdata_service_ladir = \
    $(includedir)/gdata/service

libgdata_gdata_service_la_SOURCES = \
    Service.cc

libgdata_gdata_service_la_HEADERS = \
    Service.h

我的 test/Makefile.am 看起来像这样:

INCLUDES = -I$(top_srcdir)/src/ -I$(top_srcdir)/test/

LDADD = ../src/libgdata.la

TESTS = check_bare

noinst_PROGRAMS = gdatacalendar gdatayoutube $(TESTS)

check_bare_SOURCES = check_bare.cc

gdatacalendar_SOURCES = gdatacalendar.cc

gdatayoutube_SOURCES = gdatayoutube.cc

gdatayoutube 工作得很好。它是使用来自客户端目录而不是服务( gdata/client/libgdata_gdata_client.la )的代码的旧代码......我看不出如何从服务设置客户端之间有任何区别。:-/

**编辑#2:##

好吧,我不知道这是怎么发生的,但我想我发现了我的问题。我认为测试应用程序链接的是我正在处理的库的已安装版本,而不是 src/ 中内置的本地版本。

我将对此进行更多探索,也许下次再问一些其他问题。

4

2 回答 2

7

由于c++filt -n -s gnu-v3 _ZN5gdata7service7ServiceD1Ev产生名称:

gdata::service::Service::~Service()

您需要仔细研究该类的析构函数是否始终定义,或者是否有某种方式可以将其保留为未定义(或者,实际上,它是否已定义)。或者是否编译了包含析构函数的源文件(为什么不是Service.cc?)。使用该代码的某些文件希望为其找到一个析构函数,即使Service.cc认为没有必要。

另一种可能性是库排序错误 - 即链接行按 ABC 顺序列出库,但它们需要按 BCA 顺序或其他排列,并且您正在链接静态库。通常,如果您使用静态库链接,这会导致大量未定义的符号(但使用共享库会隐藏排序问题)。

@Ephemient 为您提供了一些关于如何找到引用析构函数的目标文件的良好指示。您还应该确定Service.oService.lo.lib/Service.o其他类似名称)是否包含析构函数 - 鉴于链接错误,它很可能不包含析构函数。

于 2009-07-21T01:48:05.263 回答
2

(已经有一个名为libgdata的现有项目,但这可能不相关。)

$ find -name '*.o' -o -name '*.a' -o -name '*.so' |
> 同时读我;做
> (nm --defined-only $i; nm -D --defined-only $i) 2>/dev/null |
> grep _ZN5gdata7service7ServiceD1Ev && echo "$i"
> 完成

这是发现符号定义在哪些对象(如果有的话)中的一种相当暴力的方法。(如果模板不在播放中,_ZN5gdata7service7ServiceD1Ev找到定义的源文件可能更容易。)gdata::service::Service

$ rm libgdata.la gdatacalendar
$ 制作

这是发现libgdata.lagdatacalendar. (libgdata_la|gdatacalendar)_(SOURCES|LIBADD)(但从适当的. 中查看应该很明显Makefile.am。)

这里有不匹配吗?

于 2009-07-21T01:47:20.520 回答