ld:a.o:in function `main‘:a.c:(.text+0x4f):undefined reference to `__stack_chk_fail()(程序员的自我修养4.1)

问题

在阅读《程序员的自我修养:链接、装载与库》的4.1节时,书中实例通过将a.o,b.o直接链接到一起形成一个新的可执行文件ab来分析重定位过程,但是在实际运行命令ld a.o b.o -e main -o ab,会报错: ld: a.o: in function main': a.c:(.text+0x4f): undefined reference to __stack_chk_fail’

/*a.c*/
extern int shared; 
int main() 
{ 
	int a = 100; 
	swap(&a, &shared); 	
	return 0; 
} 
/*b.c*/
 int shared = 1; 
 void swap(int* a, int* b) 
 { 
 *a ^= *b ^= *a ^= *b; 
 }

原因

如果想直接使用ld命令手动链接而不使用GCC编译器进行链接,就需要在链接命令中显式地包含所需的库。
在上面的错误中,缺少对__stack_chk_fail函数的引用。__stack_chk_fail函数位于C运行时库中,通常是libc库。
在高版本的gcc编译器中,进行编译的时候会默认开启栈溢出保护机制。导致编译生成的目标文件a.o和b.o中会插入对__stack_chk_fail函数的引用。

解决方法1:链接libc库

因为缺少引用的__stack_chk_fail函数位于libc库中,可以通过链接libc库来引入__stack_chk_fail函数,但这种方法会额外的引入libc库的符号,不利于学习,所以更推荐方法2.

ld a.o b.o -lc -o ab

解决方法2:禁用栈溢出保护机制

要禁用栈溢出保护机制,可以使用以下方法之一:

  1. 在编译命令中使用-fno-stack-protector选项:
gcc -c a.c -o a.o -fno-stack-protector
gcc -c b.c -o b.o -fno-stack-protector
ld a.o b.o -o ab -e mainobj

上述命令将使用GCC编译器分别对a.c和b.c进行编译,并在编译命令中使用-fno-stack-protector选项来禁用栈溢出保护机制。然后使用ld链接器将a.o和b.o文件链接在一起。
2. 修改环境变量来设置默认编译选项:

export CFLAGS="-fno-stack-protector"
gcc -c a.c -o a.o
gcc -c b.c -o b.o
ld a.o b.o -o ab -e mainobj

上述命令首先通过设置CFLAGS环境变量来将-fno-stack-protector选项设置为默认的编译选项。然后使用GCC编译器对a.c和b.c进行编译,并使用ld链接器将a.o和b.o文件链接在一起。

链接结果

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值