2014-04-09 1 views
3

저는 매력처럼 작동하는 임베디드 시스템 용 C++ 코드를 작성했습니다. 현재 작업은 PC에서이 장치의 동작을 에뮬레이션하는 것입니다. 일부 코드는 이식해야합니다. 첫 번째 테스트에서는 mingw (g ++)를 사용하고 임베디드 시스템은 STM32이고 KEIL μVision 툴 체인을 사용합니다.익명의 네임 스페이스가 정의되지 않은 참조를 발생시킵니다 - 작동합니다

필자는 컴파일러의 특수한 이상 함보다는 기능적 동작과 관련이없는 문제에 봉착했습니다. 익명 네임 스페이스에 정의 된 클래스는 전체 프로젝트에 포함되어 있기 때문에 2 개의 클래스가 있습니다. 이제 임베디드 장치에서이 컴파일 및 문제없이 실행됩니다. g ++는 정의되지 않은 참조에 대해 불평합니다!

익명 네임 스페이스 arround를 제거하고 컴파일하고 실행하면! 하지만 왜? MAIN.CPP :

#include "notmain.h" 
#include "theclass.h" 

A *ourA=NULL; 

int main() 
{ 
    theA = new A(); 
    theA->dostuff(1024); 
    sunshine sun; 
    sun.Init(); 
} 

notmain.cpp :

#include "notmain.h" 
#include "theclass.h" 

void sunshine::Init() 
{ 
    theA->dostuff(127); 
} 

notmain.h :

#ifndef NOTMAIN_H_ 
#define NOTMAIN_H_ 
class sunshine 
{ 
public: 
    void Init(); 
}; 
#endif 

theclass.h :

여기 상황을 재현 일부 예는 코드
#ifndef THECLASS_H_ 
#define THECLASS_H_ 
#include <stdio.h> 
#define theA ourA 
namespace 
{ 
    class A 
    { 
    public: 
     void dostuff(int b) 
     { 
      a = b; 
      printf("Hello: %d\n",a); 
     } 
    private: 
     int a; 
    }; 
} 
extern A *ourA; 
#endif 

er/Linker 출력 : 09:09:57 ** 구성의 증분 빌드 Testo 프로젝트의 디버그 ** 정보 : 빌드에 내부 빌더가 사용됩니다. g ++ -O0 -g3 -Wall -c -fmessage-length = 0 -o main.o ".. \ main.cpp" g ++ -O0 -g3 -Wall -c -fmessage-length = 0 -o notmain.o ".. \ notmain.cpp" g ++ -o Testo.exe notmain .o 인 main.o를 notmain.o : 오류 :에, 일을 LD 네임 스페이스 문제를 해결 제거 1 번 출구 상태

09:09:57 Build Finished (took 702ms) 

을 반환하지만 왜 컴파일 않습니다, 링크 ZN8sunshine4InitEv': D:\Projekte\Testo\Debug/../notmain.cpp:6: undefined reference to 오우 라 (大 浦) ' collect2.exe 기능에서 KEIL? 아무도 나에게 이것을 설명 할 수 있습니까?

+3

헤더 파일에 익명 네임 스페이스를 사용하지 마십시오. –

+0

어쨌든 헤더에서 이름없는 네임 스페이스를 사용하면 어떤 이점이 있습니까? +1 잘 쓰여진 질문을위한 방법. – OMGtechy

+0

@OMGtechy : clambake의 추론은 "익명의 네임 스페이스가 전체 프로젝트에 포함 되었기 때문에 *"; 하지만 익명의 네임 스페이스는 정반대의 결과를 낳습니다. – Clifford

답변

0

저는 이것이 익명의 네임 스페이스 기능의 남용이라고 제안합니다. 그것은 당신이 달성하고자하는 것과 정확히 반대입니다.

익명 네임 스페이스는 정의를 단일 번역 단위로 현지화하는 데 사용됩니다. 하나를 헤더 파일에 넣은 다음 헤더를 여러 번역 단위에 포함하면 코드에 여러 개의 독립적 인 정의가 생성됩니다.

여기에서 VC++ 일어나고있는 것은 글로벌 ourA가 MAIN.CPP에 정의 A의 하나의 로컬 정의에 대한 포인터로 인스턴스화되고 있다는 것입니다, 나중에 그 지역 정의는 더 이상 볼 수 있지만, 현재 표시 구별된다 notmain.cpp의 로컬 버전. 이름 바꾸기 ZN8sunshine4InitEv의 mangling은 독립적 인 정의를 구분하지만, name mangling은 컴파일러에 정의되어 있으며, ARM의 RealView 컴파일러 (uVision에서 사용)는이 오류를 발견하지 못하는 다른 스키마를 가지고 있다고 생각합니다.

이 오류가 RealView에 있으면 결과가 분명하지 않지만 정확하거나 적어도 정의가 잘되어 있지 않습니다.

RealView는 다른 컴파일러가 정상적으로 수행하는 경고를 발행하는 데 실제로 부족하며, 내가 발견 한 정의되지 않은 동작에 대해서는 다소 허용됩니다. MinGW/GCC와 같은 다른 툴체인을 -Werror -Wall과 함께 사용하거나 정적 분석 도구를 사용하여 코드를 정리할 필요가 있습니다.

이 문제를 해결하려면 명시 적으로 명명 된 네임 스페이스를 사용하거나 네임 스페이스를 사용하지 않아야합니다.

+0

익명 네임 스페이스는 다소 시간이 걸렸던 다른 기능의 유물입니다. 이 단계에서는 어쨌든 필요하지 않습니다. 나는 내가 의미와 완전히 일치하지 않았다는 것에 동의해야한다. 나는 네임 스페이스를 삭제할 것이다. – clambake

+0

익명의 네임 스페이스는 (정적 저장소 클래스와는 달리)'정적'링크 지정자 대신 사용할 수 있습니다. C++에서 linkage 지정자로 사용되는'static' 키워드는 익명의 네임 스페이스를 위해 더 이상 사용되지 않습니다. – Clifford

관련 문제