2013-06-21 9 views
0

_sbrk 함수에 관한 링크 오류를 이해하고 라이브러리에서이 함수 정의를 우연히 발견했습니다.C 함수 정의 및 Extern 키워드

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 (Atmel Software Framework) asf/sam/utils/syscalls/gcc/syscalls.c 디렉토리에 있습니다.

는 임베디드 환경에서 내가 _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 Software Framework에는 다른 모든 기능을 호출하는 #include <assert.h>이 포함되어있는 것으로 보입니다. 링킹 문제 가버 NDEBUG 정의한 후

#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)) 

다음과 같이 해당 헤더의 assert() 매크로 정의된다. 내가 볼 수있는 한 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은 특히 유용하지 않습니다. 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