环境
- ubuntu 18.04 64bit
- gcc 7.5.0
简介
undefined reference to
是 c/c++
编程中的经典问题,也是实际项目开发中经常会碰到的,本篇就通过一些实例,来看看类似问题是如何解决的。
准备工作
这里准备3个文件,工程入口文件 main.c
,调用的函数放在了 sub.c
中,还有个头文件 sub.h
sub.h
文件
#ifndef __SUB_H__
#define __SUB_H__
void sub();
#endif
sub.c
文件
#include <stdio.h>
void sub()
{
printf("This is sub.\n");
}
main.c
文件
#include <stdio.h>
#include "sub.h"
int main()
{
printf("This is main.\n");
sub();
return 0;
}
情况一
这里先看第一种情况,我们将源码文件一一编译成目标文件 .o
gcc -c sub.c
gcc -c main.c
接着,将 main.o
编译成可执行文件 main
gcc -o main main.o
这时候就报错了,提示找不到 sub
方法
面对这种情况,将 sub.o
加进来一起编译就能够解决
gcc -o main main.o sub.o
或者更直接一点,一个命令直接到位
gcc -o main main.c sub.c
实际上,大多数项目中都是使用 Makefile
来组织编译规则,这种情况还是非常少见的。
情况二
项目开发中,不可避免的会用到第三方的库,这时候也容易产生 undefined reference to
的问题,我们来看看
将 sub.c
编译成一个静态库
gcc -c sub.c
ar -rc libsub.a sub.o
接下来,编译可执行文件
gcc -o main main.c
可以看到,由于我们没有链接静态库 libsub.a
,因此就找不到 sub
方法,这里,将 libsub.a
加上去就能让问题消失
gcc -o main main.c libsub.a
如果调用的静态库中又调用了另一个静态库,按同样的方法添加即可,这里就不再举例了,需要注意的是库链接的顺序非常讲究,顺序错了也会出现 undefined reference to
,依赖于其它库的库一定要放在被依赖库的前面。
上述情况同样适用于动态库。
通用Makefile模板
这里提供一个基础的 Makefile
模板文件,供大家参考
CC = gcc
DEBUG =-DUSE_DEBUG
CFLAGS =-Wall
SOURCES =$(wildcard ./src/*.c)
INCLUDES =-I./include
LIB_NAMES = -lz -lm -lrt -ldl -lpthread
LIB_PATH =-L./shared_libs
OBJ =$(patsubst %.c, %.o, $(SOURCES))
TARGET = main
#links
$(TARGET):$(OBJ)
@mkdir -p build
$(CC) $(OBJ) $(LIB_PATH) $(LIB_NAMES) static_libs/libsub.a static_libs/libother.a -o build/$(TARGET)
@rm -rf $(OBJ)
#compile
%.o: %.c
$(CC) $(INCLUDES) $(DEBUG) -c $(CFLAGS) $< -o $@
.PHONY:clean
clean:
@echo "Remove linked and compiled files......"
rm -rf $(OBJ) $(TARGET) build
常见错误解决
undefined reference to `dlopen'
undefined reference to `dlerror'
undefined reference to `dlsym'
undefined reference to `dlclose'
解决方法,-ldl
undefined reference to `timer_create'
undefined reference to `timer_settime'
解决方法,-lrt