2013-06-21 6 views
0

Я пытался понять ошибку связи, которую я получаю относительно функции _sbrk, и наткнулся на это определение функции в библиотеке.C Определение функции и внешнее ключевое слово

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 имеет при использовании, как это ?

Этот файл находится в системе Atmel Software Framework (ASF) в каталоге asf/sam/utils/syscalls/gcc/syscalls.c.

Это во встроенной среде, и я получаю кучу ошибок linkrt, связанные с отсутствующими определениями _exit, _kill, _sbrk ...

Это имеет смысл для создания заглушек, но я ожидал бы, что в по меньшей мере, определение _sbrk будет работать?

Update:

Ok, так что кажется, что это может помочь добавить немного информации о том, как я связывая все это вместе.

У меня есть один исполняемый проект (который будет построен с 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 

Update 2:

Я решить мою проблему, связывающую. Похоже, что Atmel Software Framework включает в себя #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, и проголосовал за тот, который помог решить проблему связи.

+0

Вы его связываете? Я не думаю, что эти слова 'extern' делают * что угодно *. –

+0

, чтобы узнать об 'extern', проверьте этот [L1] (http://stackoverflow.com/questions/1433204/what-are-extern-variables-in-c). –

+0

@Carl Norum Да, я связываю это, но это немного сложно, поэтому я обновлю свой вопрос. – nonsensickle

ответ

3

Нет проблем, указав extern на объявление функции. От C99 6.9.1/4 "Функциональные определения":

Синтаксис

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

...

Хранение класса спецификатор, если таковые имеются, в декларации спецификаторов должно быть либо extern или static.

Тем не менее, extern на функцию defintion не особенно полезен. От C99 6.2.2/4 «зей идентификаторов»:

Для получения идентификатора объявленного с хранением класса спецификатором extern в объеме, в котором перед декларацией этого идентификатора видна, если предшествующая декларация определяет внутренней или внешняя связь, связь идентификатора с более поздним объявлением совпадает с привязкой, указанной в предыдущем объявлении. Если ни одно предварительное объявление не отображается, или если в предыдущем объявлении не указана ссылка, то идентификатор имеет внешнюю привязку.

Если декларация идентификатора для функции не имеет спецификатора класса хранения, ее привязка определяется точно так, как если бы она была объявлена ​​спецификатором класса хранения extern.

Таким образом, после первой декларации функции, любой extern на последующем объявлении функции игнорируется, даже если это первая декларация static.

+0

Спасибо, это объясняет. Я также нашел упоминание @Dayal rai о том, что «определение функции также является объявлением функции», которое полезно для понимания. Это также присутствует в вашем ответе, но не сразу очевидным. Независимо от того, что это принято. Еще раз спасибо. – nonsensickle

1

extern перед определением функции просто означает, что функция имеет внешнюю связь (which it has anyway by default).

В определении функции не должно требоваться выражение «extern», если оно есть, и оно уже видно в компиляции определения. запомнить definitions are declarations also.

+0

... в прототипе/декларации тоже не нужно. Функции, объявленные без 'static', всегда имеют внешнюю связь. –

+0

Ответ и ответ Майкла Берра вместе объясняют это совершенно. Благодаря! – nonsensickle

1

В частичном ответе на вопрос о связывании, компоновщик жалуется, что ни одна из вещей, которые она связывает вместе, например. объектные файлы (и, возможно, предварительно скомпилированные библиотеки), включают функцию _sbrk(), которая вызывается кодом, который есть. То же самое касается нескольких других библиотечных функций низкого уровня.

extern не влияет на вашу проблему.

+0

Вы правы, и я нашел, где моя проблема. Я обновляю свой вопрос с помощью найденного решения. благодаря – nonsensickle