编译和连接笔记



编译


关于inline函数

情况:

  • 如果将函数的实现放在头文件中:
  • 每一个包含该头文件的源文件都将得到一份关于该函数的定义,链接器会报函数重定义错误。
  • 如果将函数的实现放在头文件中,并且标记为 inline:
  • 每一个包含该头文件的源文件都将得到一份关于该函数的定义,但是链接器不会报错
  • 如果将函数的实现放在源文件中,但是没有标记为inline
  • 该函数可以被连接到其他编译单元中。
  • 如果将函数的实现放在源文件中,并且标记为inline:
  • 该函数对其他编译单元不可见(类似于static),其他源文件不能链接该函数库。
  • 当连接到该库的时候会出现 undefined reference to 错误。

原理:

  • 编译器在编译一个inline函数时,需要知道其完整定义,如果编译器在本编译单元找不到inline函数定义就会报错。
  • inline函数的调用不涉及到函数的调用,所以不需要链接器参与工作,所以也就不会去其他编译单元查找函数定义。
  • 同理。将类的成员函数的实现放在头文件中不会出现重定义错误,是因为在类中定义成员函数默认为inline函数。

建议:

  • 如果inline函数需要,在多个源文件中被调用(类似于extern):
  1. 将函数的声明放在头文件中,无需标记为inline
  2. 将函数的实现放在头文件中,并且标记为inline
  • 如果inline函数需要,只在本地一个源文件中被调用(类似于static):
  1. 将函数的声明放在源文件中,无需标记为inline
  2. 将函数的实现放在源文件中,并且标记为inline

原理:

  • inline是一种用于实现的关键字,而不是一种用于声明的关键字。所以声明时,无需标记为inline

ref:
(关于inline函数的分析:undefined reference to)[https://blog.csdn.net/gw569453350game/article/details/77934568]


去除编译时的 声明过但从未定义 错误。

CFLAGS+=-fgnu89-inline 可以去除 声明过但从未定义 错误。

使用场景:

无法修改源码。

原理:

man gcc
>	-fgnu89-inline
>		The option -fgnu89-inline tells GCC to use the traditional GNU semantics for "inline" functions when in C99 mode.
>		  This option is accepted and ignored by GCC versions 4.1.3 up to but not including 4.3.  
>		In GCC versions 4.3 and later it changes the behavior of GCC in C99 mode.  
>		Using this option is roughly equivalent to adding the "gnu_inline" function attribute to all inline functions.
>		
>		The option -fno-gnu89-inline explicitly tells GCC to use the C99 semantics for "inline" when in C99 or gnu99 mode (i.e., it specifies the default behavior).  
>		This option was first supported in GCC 4.3.
>		This option is not supported in -std=c90 or -std=gnu90 mode.
>		
>		The preprocessor macros "__GNUC_GNU_INLINE__" and "__GNUC_STDC_INLINE__" may be used to check which semantics are in effect for "inline" functions.


链接


去除连接时的 undefined reference to 错误。

LDFLAGS+=--allow-shlib-undefined 可以去除 undefined reference to 错误。

使用场景:

使用已经编译好的库。而且已经确认,没有调用到未定义的函数。

原理:

# man ld

>	low-shlib-undefined
>	-allow-shlib-undefined
>		Allows or disallows undefined symbols in shared libraries.  This switch is similar to --no-undefined except that it determines the behaviour when the
>		undefined symbols are in a shared library rather than a regular object file.  It does not affect how undefined symbols in regular object files are handled.
>		
>		The default behaviour is to report errors for any undefined symbols referenced in shared libraries if the linker is being used to create an executable, but to allow them if the linker is being used to create a shared library.
>		
>		The reasons for allowing undefined symbol references in shared libraries specified at link time are that:
>		
>		·   A shared library specified at link time may not be the same as the one that is available at load time, so the symbol might actually be resolvable at load time.
>		
>		·   There are some operating systems, eg BeOS and HPPA, where undefined symbols in shared libraries are normal.

查看 程序的依赖库

当运行可执行文件出现找不到动态链接库错误的时候。检查库的路径是很重要的。

方法:

查看可执行文件动态链接库所依赖的库。

	# 可执行文件
	ldd <executable_file>
	
	# 动态链接库
	ldd <shared_library>

查看 已登记的库

仔细检查其中的库的路径。可以帮助了解动态链接库是否正确登记。

方法:

打印系统中已登记的库的路径。

	ldconfig -p

登记动态链接库(临时)

在测试的时候。可以临时登记动态链接库

方法:

临时登记动态链接库。(使用动态链接库的文件夹

	ldconfig <folder_of_shared_libraries>

临时登记动态链接库。(使用动态链接库的文件

	ldconfig -l <file_path_of_shared_libraries> 

注意:
这个方法只是临时登记到系统中。
如果有人再次运行ldconfig登记别的路径。则会本次的登记信息可能会被清理。


登记动态链接库(长久)

动态链接库的文件夹名称,写到配置文件。
然后将配置文件。防止到以下目录。可以保证永久的登记好动态链接库

ldconfig 系统路径

	/etc/ld.so.conf.d

配置文件路径:

	cat /etc/ld.so.conf.d/opencv.conf 

配置文件内容:

	/usr/local/lib

注意
配置文件中,可以添加多个文件夹路径。
一行一个文件夹路径。


独立的动态链接库

如果有独立的动态链接库,放置在 <folder_of_standalone_library>
而且独立的动态链接库,只想在运行 <standalone_precess> 的时候,可以被调用得到。
那么需要在运行 <standalone_precess> 之前,将 <folder_of_standalone_library> 添加到 LD_LIBRARY_PATH 本地环境变量即可。

	LD_LIBRARY_PATH=<folder_of_standalone_library>:${LD_LIBRARY_PATH}  <standalone_precess> 

猜你喜欢

转载自blog.csdn.net/yk_wing4/article/details/88982185