如何解决 IDE 链接文件过多时的栈溢出错误

如何解决 IDE 链接文件过多时的栈溢出错误

问:IDE 链接文件过多时的栈溢出错误。
我们在移植时一个大型工程时,IDE可能在最后链接时报了栈溢出的错误,绝大部分情况下原因为需要链接的文件过多,导致最后一条链接命令太长,超过工具限制的 16K 字节。
一般的解决方案为:缩小路径长度,或者将一部分文件打包为一个动态库,最后一起链接,以减少链接命令的长度。但这些方案对于一个标准的工程来说,不太合理。

解决方法:
在编译器链接时,将链接每个a.o、b.o、c.o的命令替换为链接*.o,可避免命令过长的问题。为达到此目的,可在最后一步链接失败后,打开 CMD 手动敲命令。但对于工程的标准流程来说,比较繁琐,且存在可能遗漏目录的问题。这里通过修改 makefile 链接规则,达到一劳永逸的目的。


使用范例:
  1. [CMD] make all

输出:

  1.  i386-sylixos-elf-gcc -march=pentium -mhard-float -Wl,-shared -fPIC -shared  ./Debug/obj/test_big_pro/src/*.o ./Debug/obj/test_big_pro/src/1/*.o ./Debug/obj/test_big_pro/src/2/*.o -L"/home/coder/workspace/ztc_work/coder/base_X86_pentium_1_9_9_10_debug2/libsylixos/Debug" -L"/home/coder/workspace/ztc_work/coder/base_X86_pentium_1_9_9_10_debug2/libsylixos/Release"   -lvpmpdm -lm -lgcc -o Debug/test_big_pro
  2. i386-sylixos-elf-strip  Debug/test_big_pro -o Debug/strip/test_big_pro
  3. ...
  4. i386-sylixos-elf-gcc -march=pentium -mhard-float -Wl,-shared -fPIC -shared  ./Debug/obj/test_big_pro2/src/*.o ./Debug/obj/test_big_pro2/src/1/*.o ./Debug/obj/test_big_pro2/src/2/*.o -L"/home/coder/workspace/ztc_work/coder/base_X86_pentium_1_9_9_10_debug2/libsylixos/Debug" -L"/home/coder/workspace/ztc_work/coder/base_X86_pentium_1_9_9_10_debug2/libsylixos/Release"   -lvpmpdm -lm -lgcc -o Debug/test_big_pro2
  5. i386-sylixos-elf-strip  Debug/test_big_pro2 -o Debug/strip/test_big_pro2
  6. create  ./Debug/test_big_pro ./Debug/strip/test_big_pro ./Debug/test_big_pro2 ./Debug/strip/test_big_pro2 success.

修改步骤:
截取编译时 LOCAL_SRCS 的目录,前缀补为 $(OBJPATH)/$(target),排序去重,后缀补为 *.o,处理为自定义的 OBJS,链接时调用处理完成的 OBJS 即可。

     
原 common.mk :
  1. $(target)_OBJS := $(addprefix $(OBJPATH)/$(target)/, $(addsuffix .o, $(basename $(LOCAL_SRCS))))
  2. $(target)_DEPS := $(addprefix $(DEPPATH)/$(target)/, $(addsuffix .d, $(basename $(LOCAL_SRCS))))
  3. ifeq ($(ARCH), c6x)
  4. $(target)_PPS  := $(addprefix $(DEPPATH)/$(target)/, $(addsuffix .pp, $(basename $(LOCAL_SRCS))))
  5. endif
修改后 common.mk (自定义宏处理字符串)
  1. $(target)_OBJS := $(addprefix $(OBJPATH)/$(target)/, $(addsuffix .o, $(basename $(LOCAL_SRCS))))
  2. #=========================================================================================================
  3. $(target)_DIR_OBJS := $(addsuffix *.o, $(sort $(addprefix $(OBJPATH)/$(target)/,  $(dir $(LOCAL_SRCS)))))
  4. #=========================================================================================================
  5. $(target)_DEPS := $(addprefix $(DEPPATH)/$(target)/, $(addsuffix .d, $(basename $(LOCAL_SRCS))))
  6. ifeq ($(ARCH), c6x)
  7. $(target)_PPS  := $(addprefix $(DEPPATH)/$(target)/, $(addsuffix .pp, $(basename $(LOCAL_SRCS))))
  8. endif

   

  原 application.mk :
  1. $($(target)_EXE): $($(target)_OBJS) $($(target)_DEPEND_TARGET)
  2.         @rm -f $@
  3.         $(__PRE_LINK_CMD)
  4.         $(__LD) $(__CPUFLAGS) $(ARCH_PIC_LDFLAGS) $(__LINKFLAGS) $(__OBJS) $(__LIBRARIES) -o $@
  5.         $(__POST_LINK_CMD)
修改后 application.mk (将__OBJS替换为自定义的宏):
  1. $($(target)_EXE): $($(target)_OBJS) $($(target)_DEPEND_TARGET)
  2.         @rm -f $@
  3.         $(__PRE_LINK_CMD)
  4.         $(__LD) $(__CPUFLAGS) $(ARCH_PIC_LDFLAGS) $(__LINKFLAGS) $($(@F)_DIR_OBJS) $(__LIBRARIES) -o $@
  5.         $(__POST_LINK_CMD)
 
注意:
makefile 的规则要求,前面不是空格,是两个 tab。这里以 app 做例子,如果是动态库就去 library.mk 里改就行。由于最后的链接参数是*.o,如果修改了工程的编译文件数量,build 前需要 clean。

    • Related Articles

    • 链接器堆栈溢出错误

      Q:工程里的源文件比较多,每个文件都能编译,但是链接时报错,提示链接器堆栈溢出等错误,怎么办? 在 IDE 设置中,启用短命令,如下图所示:
    • 编译过程链接文件顺序修改

      Q:编译过程链接时的 .o文件顺序问题,这个在哪儿改,在 linux 是直接修改 makfile 解决的,SylixOS 在哪里修改? 需要手动修改顺序,首先的关闭ide自动扫描添加源文件功能 如图所示 然后再 工程名.mk 文件里面修改源文件顺序 该方法的弊端,就是后续 需要新增或者删除源文件,需要手动改 xxx.mk 文件。 Do not scan source files 这个地方记得不要打开,否则每次编译 IDE 都会重新扫描排序 相关文章:文件名或扩展名太长问题 ...
    • Linux工程移植笔记-基于arping案例

      1. arping简介 arp(Address Resultion Protocol)地址解析协议,是通过解析网络层地址来找寻数据链路层地址。 ...
    • 应用程序崩溃,没有输出任何信息,如何定位?

      Q:应用程序崩溃,但没有输出任何信息,如何定位呢? 1,考虑是否栈溢出或者函数调用栈被破坏。 2,如何验证是否是栈溢出导致的呢? 在 SylixOS 上可以通过Shell 命令 调大调用栈。 //比如通过如下命令,将栈调大一倍,默认栈大小是65535shstack 120000 也有可能是栈变量等被改写,这就需要结合代码进行分析。 在嵌入式系统中,函数中最好不要定义太大的局部变量,这很容易导致栈溢出,并浪费很多时间来定位无明显提示信息的程序 Crash。 更多扩展知识见: ...
    • VxWorks 程序到 SylixOS 之移植指南

      一般来说,VxWorks程序又可分为内核程序和应用程序,内核程序又可分为BSP程序和内核模块程序。 本文重点阐述内核程序的移植。 SylixOS如何操作硬件: VxWorks如何操作硬件: 1、工程的选择 VxWorks 工程类型: SylixOS 工程类型: 2、VxWorksBSP中自定义函数被外部模块使用,在SylixOS中需要增加到符号表中,可以通过API_SymbolAddStatic或者LW_SYMBOL宏修饰方式增加。 ...