修复CC项目的ldquo未



本教程说明如何解决与C/C++项目中缺少符号有关的各种问题。我们将创建一个基本项目,从libpng库中调用png_create_read_struct()函数,并将执行常见的缺少设置步骤,解释将出现的错误。

在开始之前,请安装VisualGDB5.4或更高版本。

1.启动VisualStudio并找到VisualGDBLinuxProjectWizard:

2.选择项目的名称和位置:

3.按“Create”以启动向导中特定于VisualGDB的部分。在第一页上,选择“Createanewproject-Application-MSBuild”:

4.在本教程中,我们将使用在Windows上运行并为Linux目标构建代码的跨工具链,并将演示此配置导致的故障点。但是,下面显示的大多数步骤也适用于直接在Linux上构建的项目:

5.按“Finish”以生成项目。现在,我们将尝试从libpng库中调用一个函数,并将执行可能会导致构建时或运行时错误的大多数可能丢失的步骤。将以下代码添加到main()函数,然后尝试构建项目:

png_create_read_struct(NULL,NULL,NULL,NULL);

6.现在,构建将因以下错误而失败:

MissingSymbolDemo.cpp:Infunctionintmain(int,char**):

MissingSymbolDemo.cpp:7:5:error:png_create_read_structwasnotdeclaredinthisscope

png_create_read_struct(NULL,NULL,NULL,NULL);

^~~~~~~~~~~~~~~~~~~~~~

7.您可以通过右键单击错误消息并选择“GotoBuildLog”来找到GCC的确切输出:

8.错误“png_create_read_struct’wasnotdeclaredinthisscope”,表示C/C++编译器不知道png_create_read_struct符号。它无法确定它是函数,全局函数指针还是预处理器宏。要解决此错误,需要声明png_create_read_struct()函数。声明如下:

png_structppng_create_read_struct(png_const_charpuser_png_ver,png_voidperror_ptr,png_error_ptrerror_fn,png_error_ptrwarn_fn);

9.由于将每个函数声明复制到每个源文件中是不切实际的,因此大多数C/C++库都提供列出所有相关声明的头文件。通常,您可以在文档中找到头文件名,并将其包含在程序中,如下所示:

#includepng.h

这等同于将头文件内容复制并粘贴到源文件中。

10.包含头文件将不会在整个构建机器中搜索它。相反,GCC将仅搜索几个常见位置(例如/usr/include),并且在项目设置中指定头搜索目录。在我们的示例中,png.h文件位于工具链的/usr/include/libpng目录中,最初不会被找到,从而产生以下错误:

MissingSymbolDemo.cpp:2:10:fatalerror:png.h:Nosuchfileordirectory

#includepng.h

^~~~~~~

11.VisualGDB通常会在附近目录中搜索缺少的标头,并建议自动修复设置。如果您是手动配置项目,则只需在构建计算机上找到头文件,然后将其目录添加到“IncludeDirectories”字段中即可:

请注意,如果您使用的是跨工具链,则该头文件必须位于其sysroot目录中(例如/usr/include/libpng/png.h对应于E:\sysgcc\raspberry\arm-linux-gnueabihf\sysroot\usr\include\libpng\png.h)。如果使用的是在Windows上运行的跨工具链,则需要指定Windows计算机上文件的路径(即$(ToolchainDir)\arm-linux-gnueabihf\sysroot\usr\include\libpng\png。H)。为了方便起见,GCC会自动用sysroot目录替换路径开头的“=”,因此本示例中正确的包含目录应为=/usr/include/libpng/png.h(请注意开头的“=”)。

12.如果您现在构建项目,它将失败并出现另一个错误:

C:\projects\temp\MissingSymbolDemo/MissingSymbolDemo.cpp:9:undefinedreferenceto`png_create_read_struct

Buildfailed:arm-linux-gnueabihf-g++.exeexitedwithcode1

collect2.exe:error:ldreturned1exitstatus

13.发生这种情况是因为png.h文件仅包含png_create_read_struct()函数的声明。即,它定义了它的返回类型和参数类型(让GCC在编译时检查它们),但是它没有提供实现。函数实现通常位于静态库(.a文件)或共享库(.so文件)中。通过搜索所有包含png_create_read_struct文本的.a和.so文件,可以找到正确的库名称。如果找到了几个库,请使用objdump-T.sofile或objdump-t.afile命令列出该库导出的所有符号:

e8fcgDF.text0024PNG16_0png_create_read_struct

如果您要查找的符号列出的地址非零(第一列),则说明您找到了正确的库。否则,该库将导入该符号,而不是将其导出。

14.在此示例中,定义png_create_read_struct()的库称为libpng.so。您可以通过将其名称(不带lib前缀)添加到“LibraryNames”字段中来链接到您的项目,只要它位于标准库目录中即可。如果没有,您还需要将库目录添加到“LibraryDirectories”字段中:

15.现在您可以成功构建项目:

如果构建仍然失败,则可能在标头中缺少extern“C”子句。

16.最后,我们将演示运行时错误。将构建的程序部署到目标并运行“ldBinaryName”:

17.LDD命令将显示该文件所需的共享库。在本教程中,我们将所有libpng*库移动到/usr/lib/arm-linux-gnueabihf/png子目录,并显示将发生的情况。移动库后,开始使用VisualGDB调试项目,并在“DebugOutput”中观察以下错误消息:

/tmp/MissingSymbolDemo:errorwhileloadingsharedlibraries:libpng16.so.16:cannotopensharedobjectfile:Nosuchfileordirectory

VisualGDB会自动建议在目标上定位文件:

18.在移动目录libpng16.so中找到它,然后按“OK”:

19.这将自动将库的目录添加到项目的LD_LIBRARY_PATH变量中,因此现在您将能够成功启动它:

20.如果您是手动运行项目,只需将缺少的.so文件的目录添加到LD_LIBRARY_PATH变量中(如下所示),就可以对其进行处理:

由于我们已将NULL传递给png_create_read_struct()而不是libpng版本数字,它将显示警告消息。您可以通过将PNG_LIBPNG_VER_STRING作为第一个参数传递给png_create_read_struct()来消除它。

VisualGDB使使用VisualStudio的跨平台开发变得轻松而舒适

预览时标签不可点收录于话题#个上一篇下一篇


转载请注明:http://www.imbnc.com/mlyhl/12416.html