C函数定义和外部关键字

时间:2013-06-21 04:17:08

标签: c function extern cortex-m3 atmel

我一直在努力理解我在_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的遗漏定义有关的链接错误...

生成存根是有意义的,但我原本预计至少会给出_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问题的答案,并投票支持解决链接问题的答案。

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

函数定义前面的extern意味着该函数具有外部链接(which it has anyway by default)

只要声明具有并且已经在定义的编译中看到,就不应该在函数定义上要求'extern'。 请记住definitions are declarations also

答案 2 :(得分:1)

在对链接问题的部分回答中,链接器抱怨它没有连接在一起的东西,例如目标文件(可能还有预编译的库)包括_sbrk()函数,该函数由 中的代码调用。其他几个低级库函数也是如此。

extern不会影响您的问题。