0

我一直在试图理解我得到的关于 _sbrk 函数的链接错误,并在库中偶然发现了这个函数定义。

extern caddr_t _sbrk(int incr);

// ... some other definitions ...

extern caddr_t _sbrk(int incr)
{
static unsigned char *heap = NULL;
unsigned char *prev_heap;

if (heap == NULL) {
    heap = (unsigned char *)&_end;
}
prev_heap = heap;

heap += incr;

return (caddr_t) prev_heap;
}

现在,我知道extern函数声明中的作用,但在函数定义中使用时我不知道它的含义......

有谁知道这样extern使用有什么意义?

有问题的文件位于asf/sam/utils/syscalls/gcc/syscalls.c目录中的 Atmel 软件框架 (ASF) 中。

它在嵌入式环境中,我收到一堆与缺少_exit, _kill, _sbrk...的定义有关的 linkrt 错误

生成存根是有意义的,但我希望至少_sbrk给出的定义会起作用?

更新:

好的,所以添加一些关于我如何将所有这些链接在一起的信息似乎可能会有所帮助。

我有一个可执行项目(使用 GCC 构建),我有一个链接到生成的可执行文件(也使用 GCC 构建)的静态库项目。

它们都没有启用优化(它可以更容易地在嵌入式目标上进行调试,而不会像在药物上那样跳跃)。

静态库包括上面提到的 ASF 代码。ASF 由 Atmel Studio 6.0 中包含的某个向导自动生成。

静态库中的一些代码包括<stdio.h>我的目的不需要的代码,但我真的不想更改自动生成的代码(它必然会撤消我的更改)。

来自链接器的错误如下:

Invoking: ARM/GNU Linker : (crosstool-NG 1.15.3 - Atmel build: 59) 4.7.0
    "C:\Program Files (x86)\Atmel\Atmel Studio 
6.0\extensions\Atmel\ARMGCC\3.3.1.128\ARMGCCToolchain\bin\arm-none-eabi-gcc.exe" -o 
Bootloader_Stage1.elf  cmsis/src/startup_sam3n.o cmsis/src/system_sam3n.o 
Bootloader_Stage1.o   -Wl,-Map="Bootloader_Stage1.map" -Wl,--start-group -lm -
lBootloaderShared  -Wl,--end-group -L"../cmsis/linkerScripts" -
L"../../BootloaderShared/Debug"  -Wl,--gc-sections -Tsam3n4b_flash.ld  -mcpu=cortex-m3 
    c:/program files (x86)/atmel/atmel studio 
6.0/extensions/atmel/armgcc/3.3.1.128/armgcctoolchain/bin/../lib/gcc/arm-none-
eabi/4.7.0/../../../../arm-none-eabi/lib/thumb\libc.a(lib_a-abort.o): In function 
`abort':
/usr/local/avr32studio/hudson/workspace/arm-gnu-toolchain/.build/src/newlib-
1.19.0/newlib/libc/stdlib/abort.c(63,1): undefined reference to `_exit'
    c:/program files (x86)/atmel/atmel studio 
6.0/extensions/atmel/armgcc/3.3.1.128/armgcctoolchain/bin/../lib/gcc/arm-none-
eabi/4.7.0/../../../../arm-none-eabi/lib/thumb\libc.a(lib_a-sbrkr.o): In function 
`_sbrk_r':
/usr/local/avr32studio/hudson/workspace/arm-gnu-toolchain/.build/src/newlib-
1.19.0/newlib/libc/reent/sbrkr.c(60,1): undefined reference to `_sbrk'
    c:/program files (x86)/atmel/atmel studio 
6.0/extensions/atmel/armgcc/3.3.1.128/armgcctoolchain/bin/../lib/gcc/arm-none-
eabi/4.7.0/../../../../arm-none-eabi/lib/thumb\libc.a(lib_a-signalr.o): In function 
`_kill_r':
/usr/local/avr32studio/hudson/workspace/arm-gnu-toolchain/.build/src/newlib-
1.19.0/newlib/libc/reent/signalr.c(61,1): undefined reference to `_kill'
    c:/program files (x86)/atmel/atmel studio 
6.0/extensions/atmel/armgcc/3.3.1.128/armgcctoolchain/bin/../lib/gcc/arm-none-
eabi/4.7.0/../../../../arm-none-eabi/lib/thumb\libc.a(lib_a-signalr.o): In function 
`_getpid_r':
/usr/local/avr32studio/hudson/workspace/arm-gnu-toolchain/.build/src/newlib-
1.19.0/newlib/libc/reent/signalr.c(96,1): undefined reference to `_getpid'
    c:/program files (x86)/atmel/atmel studio 
6.0/extensions/atmel/armgcc/3.3.1.128/armgcctoolchain/bin/../lib/gcc/arm-none-
eabi/4.7.0/../../../../arm-none-eabi/lib/thumb\libc.a(lib_a-writer.o): In function 
`_write_r':
/usr/local/avr32studio/hudson/workspace/arm-gnu-toolchain/.build/src/newlib-
1.19.0/newlib/libc/reent/writer.c(58,1): undefined reference to `_write'
    c:/program files (x86)/atmel/atmel studio 
6.0/extensions/atmel/armgcc/3.3.1.128/armgcctoolchain/bin/../lib/gcc/arm-none-
eabi/4.7.0/../../../../arm-none-eabi/lib/thumb\libc.a(lib_a-closer.o): In function 
`_close_r':
/usr/local/avr32studio/hudson/workspace/arm-gnu-toolchain/.build/src/newlib-
1.19.0/newlib/libc/reent/closer.c(53,1): undefined reference to `_close'
    c:/program files (x86)/atmel/atmel studio 
6.0/extensions/atmel/armgcc/3.3.1.128/armgcctoolchain/bin/../lib/gcc/arm-none-
eabi/4.7.0/../../../../arm-none-eabi/lib/thumb\libc.a(lib_a-fstatr.o): In function 
`_fstat_r':
/usr/local/avr32studio/hudson/workspace/arm-gnu-toolchain/.build/src/newlib-
1.19.0/newlib/libc/reent/fstatr.c(62,1): undefined reference to `_fstat'
    c:/program files (x86)/atmel/atmel studio 
6.0/extensions/atmel/armgcc/3.3.1.128/armgcctoolchain/bin/../lib/gcc/arm-none-
eabi/4.7.0/../../../../arm-none-eabi/lib/thumb\libc.a(lib_a-isattyr.o): In function 
`_isatty_r':
/usr/local/avr32studio/hudson/workspace/arm-gnu-toolchain/.build/src/newlib-
1.19.0/newlib/libc/reent/isattyr.c(58,1): undefined reference to `_isatty'
    Invoking: ARM/GNU Linker : (crosstool-NG 1.15.3 - Atmel build: 59) 4.7.0
    "C:\Program Files (x86)\Atmel\Atmel Studio 
6.0\extensions\Atmel\ARMGCC\3.3.1.128\ARMGCCToolchain\bin\arm-none-eabi-gcc.exe" -o 
Bootloader_Stage1.elf  cmsis/src/startup_sam3n.o cmsis/src/system_sam3n.o 
Bootloader_Stage1.o   -Wl,-Map="Bootloader_Stage1.map" -Wl,--start-group -lm -
lBootloaderShared  -Wl,--end-group -L"../cmsis/linkerScripts" -
L"../../BootloaderShared/Debug"  -Wl,--gc-sections -Tsam3n4b_flash.ld  -mcpu=cortex-m3 
    c:/program files (x86)/atmel/atmel studio 
6.0/extensions/atmel/armgcc/3.3.1.128/armgcctoolchain/bin/../lib/gcc/arm-none-
eabi/4.7.0/../../../../arm-none-eabi/lib/thumb\libc.a(lib_a-abort.o): In function 
`abort':
/usr/local/avr32studio/hudson/workspace/arm-gnu-toolchain/.build/src/newlib-
1.19.0/newlib/libc/stdlib/abort.c(63,1): undefined reference to `_exit'
    c:/program files (x86)/atmel/atmel studio 
6.0/extensions/atmel/armgcc/3.3.1.128/armgcctoolchain/bin/../lib/gcc/arm-none-
eabi/4.7.0/../../../../arm-none-eabi/lib/thumb\libc.a(lib_a-sbrkr.o): In function 
`_sbrk_r':
/usr/local/avr32studio/hudson/workspace/arm-gnu-toolchain/.build/src/newlib-
1.19.0/newlib/libc/reent/sbrkr.c(60,1): undefined reference to `_sbrk'
    c:/program files (x86)/atmel/atmel studio 
6.0/extensions/atmel/armgcc/3.3.1.128/armgcctoolchain/bin/../lib/gcc/arm-none-
eabi/4.7.0/../../../../arm-none-eabi/lib/thumb\libc.a(lib_a-signalr.o): In function  
`_kill_r':
/usr/local/avr32studio/hudson/workspace/arm-gnu-toolchain/.build/src/newlib-
1.19.0/newlib/libc/reent/signalr.c(61,1): undefined reference to `_kill'
    c:/program files (x86)/atmel/atmel studio 
6.0/extensions/atmel/armgcc/3.3.1.128/armgcctoolchain/bin/../lib/gcc/arm-none-
eabi/4.7.0/../../../../arm-none-eabi/lib/thumb\libc.a(lib_a-signalr.o): In function 
`_getpid_r':
/usr/local/avr32studio/hudson/workspace/arm-gnu-toolchain/.build/src/newlib-
1.19.0/newlib/libc/reent/signalr.c(96,1): undefined reference to `_getpid'
    c:/program files (x86)/atmel/atmel studio 
6.0/extensions/atmel/armgcc/3.3.1.128/armgcctoolchain/bin/../lib/gcc/arm-none-
eabi/4.7.0/../../../../arm-none-eabi/lib/thumb\libc.a(lib_a-writer.o): In function 
`_write_r':
/usr/local/avr32studio/hudson/workspace/arm-gnu-toolchain/.build/src/newlib-
1.19.0/newlib/libc/reent/writer.c(58,1): undefined reference to `_write'
    c:/program files (x86)/atmel/atmel studio 
6.0/extensions/atmel/armgcc/3.3.1.128/armgcctoolchain/bin/../lib/gcc/arm-none-
eabi/4.7.0/../../../../arm-none-eabi/lib/thumb\libc.a(lib_a-closer.o): In function 
`_close_r':
/usr/local/avr32studio/hudson/workspace/arm-gnu-toolchain/.build/src/newlib-
1.19.0/newlib/libc/reent/closer.c(53,1): undefined reference to `_close'
    c:/program files (x86)/atmel/atmel studio 
6.0/extensions/atmel/armgcc/3.3.1.128/armgcctoolchain/bin/../lib/gcc/arm-none-
eabi/4.7.0/../../../../arm-none-eabi/lib/thumb\libc.a(lib_a-fstatr.o): In function 
`_fstat_r':
/usr/local/avr32studio/hudson/workspace/arm-gnu-toolchain/.build/src/newlib-
1.19.0/newlib/libc/reent/fstatr.c(62,1): undefined reference to `_fstat'
    c:/program files (x86)/atmel/atmel studio 
6.0/extensions/atmel/armgcc/3.3.1.128/armgcctoolchain/bin/../lib/gcc/arm-none-
eabi/4.7.0/../../../../arm-none-eabi/lib/thumb\libc.a(lib_a-isattyr.o): In function 
`_isatty_r':
/usr/local/avr32studio/hudson/workspace/arm-gnu-toolchain/.build/src/newlib-
1.19.0/newlib/libc/reent/isattyr.c(58,1): undefined reference to `_isatty'
    c:/program files (x86)/atmel/atmel studio 
6.0/extensions/atmel/armgcc/3.3.1.128/armgcctoolchain/bin/../lib/gcc/arm-none-
eabi/4.7.0/../../../../arm-none-eabi/lib/thumb\libc.a(lib_a-lseekr.o): In function 
`_lseek_r':
/usr/local/avr32studio/hudson/workspace/arm-gnu-toolchain/.build/src/newlib-
1.19.0/newlib/libc/reent/lseekr.c(58,1): undefined reference to `_lseek'
    c:/program files (x86)/atmel/atmel studio 
6.0/extensions/atmel/armgcc/3.3.1.128/armgcctoolchain/bin/../lib/gcc/arm-none-
eabi/4.7.0/../../../../arm-none-eabi/lib/thumb\libc.a(lib_a-readr.o): In function 
`_read_r':
/usr/local/avr32studio/hudson/workspace/arm-gnu-toolchain/.build/src/newlib-
1.19.0/newlib/libc/reent/readr.c(58,1): undefined reference to `_read'
collect2.exe(0,0): ld returned 1 exit statusc:/program files (x86)/atmel/atmel studio 
6.0/extensions/atmel/armgcc/3.3.1.128/armgcctoolchain/bin/../lib/gcc/arm-none-
eabi/4.7.0/../../../../arm-none-eabi/lib/thumb\libc.a(lib_a-lseekr.o): In function 
`_lseek_r':
/usr/local/avr32studio/hudson/workspace/arm-gnu-toolchain/.build/src/newlib-
1.19.0/newlib/libc/reent/lseekr.c(58,1): undefined reference to `_lseek'
    c:/program files (x86)/atmel/atmel studio  
6.0/extensions/atmel/armgcc/3.3.1.128/armgcctoolchain/bin/../lib/gcc/arm-none-
eabi/4.7.0/../../../../arm-none-eabi/lib/thumb\libc.a(lib_a-readr.o): In function 
`_read_r':
/usr/local/avr32studio/hudson/workspace/arm-gnu-toolchain/.build/src/newlib-
1.19.0/newlib/libc/reent/readr.c(58,1): undefined reference to `_read'
collect2.exe(0,0): ld returned 1 exit status

更新 2:

我已经解决了我的链接问题。似乎 Atmel 软件框架包括#include <assert.h>调用所有其他函数的那个​​。在该标题中,assert()宏定义如下

#ifdef NDEBUG           /* required by ANSI standard */
# define assert(__e) ((void)0)
#else
# define assert(__e) ((__e) ? (void)0 : __assert_func (__FILE__, __LINE__, \
                           __ASSERT_FUNC, #__e))

定义 NDEBUG 后,链接问题就消失了。据我所见NDEBUG,没有在其他任何地方使用(不删除我依赖的任何其他代码),所以我可以保留定义的符号。

正如我之前提到的,我已经接受了回答问题的答案extern并投票给了有助于解决链接问题的答案。

4

3 回答 3

3

extern在函数声明上指定没有问题。从 C99 6.9.1/4“函数定义”开始:

句法

function-definition:
    declaration-specifiers declarator declaration-list[opt] compound-statement

...

声明说明符中的存储类说明符(如果有)应为externstatic

但是,extern函数定义并不是特别有用。从 C99 6.2.2/4“标识符的链接”开始:

对于在该标识符的先前声明可见的范围内使用存储类说明符extern声明的标识符,如果先前声明指定内部或外部链接,则后面声明的标识符的链接与指定的链接相同在事先声明。如果前面的声明不可见,或者前面的声明没有指定链接,则标识符具有外部链接。

如果函数标识符的声明没有存储类说明符,则它的链接将完全确定,就好像它是使用存储类说明符声明的一样extern

因此,在函数的第一个声明之后,extern后续函数声明中的任何内容都将被忽略,即使该第一个声明是static.

于 2013-06-21T06:56:47.230 回答
1

函数定义前面的 extern 只是表示该函数具有外部链接(which it has anyway by default)

只要声明有它并且已经在定义的编译中看到,函数定义就不需要“extern”。记住definitions are declarations also

于 2013-06-21T05:42:01.263 回答
1

在对链接问题的部分回答中,链接器抱怨它链接在一起的所有东西,例如目标文件(以及可能的预编译库),都不包括 _sbrk() 函数,该函数那里。其他几个低级库函数也是如此。

extern 不会影响您的问题。

于 2013-06-21T06:58:41.207 回答