Skip to content

Ld:Troubleshooting

ld 사용중 발생할 수 있는 문제점에 대한 정리.

undefined reference to 'xxx'

컴파일까지는 잘되는데 링크를 하면 아래와 같은 링크에러가 발생된다.

undefined reference to `xxx' (xxx는 함수명 또는 전역변수명)

.a파일을 같이 link할 때, -l(라이브러리) 뿐만 아니라, 직접 lib(어쩌구저쩌구).a라는 형태로도 링크가 가능하다. 굳이 -L(path) -l(라이브러리)식으로 할 필요가 없는 것이다. 즉,

gcc -o execfile obj1.o obj2.o obj3.o firstlib.a secondlib.a

와 같은 방식으로도 적용할 수 있다.

링크할 때 적어넣는 순서를 바꿔서 해결할 수 있다. 링크할 때 심볼을 찾는 과정에서 순서를 맞추어야 하는 것이 있는 듯 하다.
아래와 같은 방법으로도 해결할 수 있다.

gcc -o exefile -Xlinker --start-group libmod1.a libmod2.a libmod3.a -Xlinker --end-group

-Xlinker는 뒤에 옵션을 링커(ld)에 넘기라는 옵션이다. 링커옵션인 --start-group--end-group는 아래와 같은 역할을 한다.

"The specified archives are searched repeatedly until no new undefined references are created."

Why is My Global or Static Constructor not Called

정적링크시 전역변수가 호출되지 않는 현상에 대하여 설명한다.

Recall that a static linker’s purpose is to look through a compilation unit for symbols marked as unresolved and then copy code from a library to define the symbol. Consider what happens if your program does not directly reference any symbol in a compilation unit contained in a given library. The linker never sees an unresolved reference to code in that object file and so it assumes that no code from that particular compilation unit is used, and therefore will ignore any global or static constructors in that file as well. In order to ensure that the global or static constructors of a compilation unit are called, you must directly reference some symbol in the compilation unit object file defining the global constructor. Note that this is a reference to an object file used to build the library, not a symbol in the library file. This means that you must have knowledge of the files that were used to build the library to make this work. For example, consider a situation where you have a static library called libnode.a; and that library is made from a number of object files.

해결방법은, --whole-archive옵션을 사용하면 된다.

undefined hidden symbol '__init_array_end'

아래와 같은 링크 오류가 발생될 수 있다.

/usr/lib/x86_64-linux-gnu/libc_nonshared.a(elf-init.oS): In function `__libc_csu_init':
(.text+0xd): undefined reference to `__init_array_end'
/usr/bin/ld: /usr/lib/x86_64-linux-gnu/libc_nonshared.a(elf-init.oS): relocation R_X86_64_PC32 against undefined hidden symbol `__init_array_end' can not be used when making a shared object
/usr/bin/ld: final link failed: Bad value
collect2: ld returned 1 exit status
make: *** [libKeynect.so] Error 1

이 경우, -Wl,--whole-archive-Wl,--no-whole-archive사이에 정적 라이브러리 플래그를 추가하면 된다.

Static library into the shared library

GCC의 --whole-archive옵션을 사용하면 된다.

$ g++ -Wl,--whole-archive some_static_lib.a -Wl,--no-whole-archive

clang을 위한 -Wl,-all_load옵션도 존재한다.

LD_LIBRARY_PATH 환경변수 설정이 안될 경우

From Ubuntu wiki help page

Note: You can only set this environment variable inside an interactive shell.
[ie a terminal ] Since Ubuntu 9.04 Jaunty Jackalope, LD_LIBRARY_PATH cannot be set in $HOME/.profile,
/etc/profile, nor /etc/environment files. You must use /etc/ld.so.conf.d/*.conf configuration files.
See Launchpad bug #366728 for more information.

How to fix it:

cd /etc/ld.so.conf.d

Make a file with the .conf extension here

sudo nano cuda.conf

Add the paths to it as two lines

/usr/local/cuda-7.5/lib64
/usr/lib/nvidia-361

Save and exit. Check with ls -l that the file has the same ownership and permissions as others in the directory, they should be:

-rw-r--r-- 1 root root

Then run

ldconfig

This doesn't set the env variable, but includes the libraries appropriately so CUDA works

Direct access to weak symbols

ld: warning: direct access in function {A} from file {B} to global weak symbol {C} from file {D} means the weak symbol cannot be overridden at runtime. This was likely caused by different translation units being compiled with different visibility settings.

라이브러리를 찾을 수 없지만 패키지로는 설치되어 있다고 출력될 때

Advanced Package Tool#라이브러리를 찾을 수 없지만 패키지로는 설치되어 있다고 출력될 때

See also