undefined reference to `__stack_chk_fail'

本文介绍了解决GCC编译过程中因栈保护引发错误的方法。通过修改Makefile中的编译选项加入-fno-stack-protector禁用栈保护功能,解决了klib.c中disp_int函数的编译错误。对比了开启与关闭栈保护时的反汇编代码差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在编译程序时klib.c中的disp_int报了该错,去网上搜了一下,在Makefile中的$(CFLAGS)后面加上-fno-stack-protector,即不需要栈保护

lib/klib.o:lib/klib.c
        $(CC) $(CFLAGS) -fno-stack-protector -o $@ $<

然后编译就可以了正常执行了

然后就自己验证了一下,将char output[16];注释掉改为char* output,编译不报错,说明问题就是由于定义数组的栈操作引起。

我反编译了一下

代码test.c:

int main()

{

    char a[16];

    return 0;

}

1.gcc  -o test test.c

gdb test

(gdb)disas main

   0x08048404 <+0>:    push   %ebp
   0x08048405 <+1>:    mov    %esp,%ebp
   0x08048407 <+3>:    and    $0xfffffff0,%esp
   0x0804840a <+6>:    sub    $0x20,%esp
   0x0804840d <+9>:    mov    %gs:0x14,%eax
   0x08048413 <+15>:    mov    %eax,0x1c(%esp)
   0x08048417 <+19>:    xor    %eax,%eax
   0x08048419 <+21>:    mov    $0x0,%eax
   0x0804841e <+26>:    mov    0x1c(%esp),%edx
   0x08048422 <+30>:    xor    %gs:0x14,%edx
   0x08048429 <+37>:    je     0x8048430 <main+44>
   0x0804842b <+39>:    call   0x8048340 <__stack_chk_fail@plt>
   0x08048430 <+44>:    leave  
   0x08048431 <+45>:    ret 

2.gcc -fno-stack-protector -o test test.c

gdb test

(gdb)disas main

   0x080483b4 <+0>:    push   %ebp
   0x080483b5 <+1>:    mov    %esp,%ebp
   0x080483b7 <+3>:    sub    $0x10,%esp
   0x080483ba <+6>:    mov    $0x0,%eax
   0x080483bf <+11>:    leave  
   0x080483c0 <+12>:    ret   


可以明显看到我电脑上的这个版本的GCC默认是要进行栈检查的要调用__stack_chk_fail,而加了-fno-stack-protector的话就不用栈检查就不用调用__stack_chk_fail

### 解决方案分析 `undefined reference to __memcpy_chk` 错误通常是由编译器启用了 `-fstack-protector` 或者类似的选项引起的。这些选项会启用堆栈保护机制,而该机制依赖一些特定的库函数(如 `__stack_chk_guard`, `__memcpy_chk` 等)。如果目标环境中缺少这些支持,则会出现未定义引用错误。 以下是可能的原因以及解决方案: #### 可能原因 1. **缺失标准 C 库的支持** 如果使用了 `-nostdlib` 编译选项,可能会导致链接阶段找不到必要的标准库函数[^1]。 2. **编译器配置问题** 启用了堆栈保护功能(如 `-fstack-protector`),但目标环境并未提供相应的支持[^2]。 3. **工具链不匹配** 工具链版本较旧,或者未正确配置以支持现代的安全特性[^4]。 --- ### 解决方法 #### 方法一:禁用堆栈保护功能 可以通过修改编译选项来关闭堆栈保护功能。具体操作如下: ```bash CFLAGS="-fno-stack-protector" CXXFLAGS="-fno-stack-protector" ``` 这可以防止编译器尝试调用诸如 `__stack_chk_guard``__memcpy_chk` 的函数。 #### 方法二:重新构建工具链并启用 SSP 支持 如果希望保留堆栈保护功能,则需要确保工具链已正确配置以支持 Stack Smashing Protection (SSP) 功能。可以在工具链配置菜单中启用此选项: ```plaintext make menuconfig ---> Toolchain Options ---> Enable Stack-Smashing Protection support ``` 完成配置后,重新构建工具链即可。 #### 方法三:手动链接所需的库文件 如果不想完全禁用堆栈保护功能,也可以通过显式链接 glibc 来解决问题。例如,在编译命令中添加以下参数: ```bash -lc -lgcc -lm ``` 这样可以确保链接到的标准库包含所需的功能实现。 #### 方法四:替换或更新工具链 对于某些老旧工具链来说,可能存在兼容性问题。考虑升级至最新版的 GCC 工具链,以便获得更好的安全特性和更全面的支持[^3]。 --- ### 示例代码调整 假设当前使用的 Makefile 配置如下: ```Makefile CC = arm-linux-gcc CFLAGS = -Wall -O2 -nostdlib LDFLAGS = TARGET = example.bin SRCS = main.c utils.c all: $(TARGET) $(TARGET): $(OBJS) $(CC) $(LDFLAGS) -o $@ $^ clean: rm -rf *.o $(TARGET) ``` 为了修复上述问题,可将 `CFLAGS` 修改为: ```Makefile CFLAGS = -Wall -O2 -fno-stack-protector ``` 同时确保链接阶段包含了必要库文件: ```Makefile LDFLAGS = -lc -lgcc -lm ``` --- ### 总结 以上提供了四种不同的解决策略,分别适用于不同场景下的需求。推荐优先尝试禁用堆栈保护功能的方法,因为这是最简单且有效的手段;但如果项目确实需要开启此类保护措施,则需确保工具链具备相应的能力和支持。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值