문제

나는 다음과 같은 오류가(그리고 해결책을 발견한 온라인,하지만 그것은 존재하지 않에 Stack Overflow):

(.하는 것입니다.linkonce.[재료]):undefined 참조[방법][체 파일]:(.하는 것입니다.linkonce.[재료]):정의되지 않은 참조하여`에 대한 않음 [classname]'

왜 하나 이들 중 하나는"정의되지 않은 참조를 않음"링 오류?

(는 경우에는 보너스 포인트 설명할 수 있는 무슨 일이 있습니다.)

도움이 되었습니까?

해결책

가능한 한 가지 이유 때문에 당신이 선언하는 가상 기능을 정의하지 않고 그것.

를 선언할 때 이를 정의하지 않고 같은 컴파일 단위,당신은 당신의 것을 나타내는 정의된 다른 곳에 이 링커 단계에 그것을 찾기 위해 노력할 것입니다 중 하나에서 다른 컴파일 장치(라이브러리)입니다.

예를 들어의 정의 가상의 기능은 다음과 같습니다

virtual void fn() { /* insert code here */ }

이 경우에,당신은 연결이 정의를 선언하는 의미의 링이 필요하지 않를 해결됩니다.

virtual void fn();

선언 fn() 를 정의하지 않고 그리고 발생한 오류 메시지가 당신에 대해 물었다.

그것은 매우 유사한 코드:

extern int i;
int *pi = &i;

미국은 정수 i 선언에서 다른 컴파일한 단위에서 해결해야 합 링크를 시간이다(그렇지 않으면 pi 설정할 수 없습니다 그것은 주소 등).

다른 팁

이것은 당신이 믹스 할 때도 일어날 수 있습니다 -fno-rtti 그리고 -frtti 암호. 그런 다음 모든 수업을 확인해야합니다. type_info 에 액세스됩니다 -frtti 코드, 주요 방법을 컴파일해야합니다 -frtti. 이러한 액세스는 클래스의 객체를 만들 때 발생할 수 있습니다. dynamic_cast 등.

[원천]

이는 선언 된 (비 퓨어) 가상 함수가 신체가 없을 때 발생합니다. 수업 정의에서 다음과 같은 것과 같습니다.

virtual void foo();

정의해야합니다 (인라인 또는 링크 된 소스 파일) :

virtual void foo() {}

또는 순수한 가상 선언 :

virtual void foo() = 0;

인용 GCC 매뉴얼:

다형성 클래스 (가상 함수가있는 클래스)의 경우, type_info 객체는 vtable [...]와 함께 기록됩니다. 객체를 던지거나 캐치 조항 또는 예외 사양의 유형을 참조합니다.

그리고 같은 페이지에서 조금 일찍 :

클래스가 비 인화, 비 구멍 가상 함수를 선언하는 경우 첫 번째는 클래스의 "키 메소드"로 선택되며 vtable은 키 메소드가 정의되는 번역 장치에서만 방출됩니다.

따라서이 오류는 이미 언급 한 것처럼 "키 메소드"에 정의가 누락 된 경우 발생합니다.

하나를 다른 사람에게 연결하는 경우 GCC 또는 G ++에서 "-fvisibility = hidden"으로 컴파일하는 가능성이 하나 더 있습니다. 두 .SO 파일이 "-fvisibility = hidden"으로 구축 된 경우 키 메소드가 동일하지 않아 가상 함수의 다른 구현과 동일하지 않으면 후자는 전자의 vtable 또는 typeinfo를 보지 못합니다. 링커에 이것은 구현되지 않은 가상 함수처럼 보입니다 (Paxdiablo와 Cdleary의 답변에서와 같이).

이 경우 기본 클래스의 가시성에 대해서도 예외를 만들어야합니다.

__attribute__ ((visibility("default")))

클래스 선언에서. 예를 들어,

class __attribute__ ((visibility("default"))) boom{
    virtual void stick();
}

물론 또 다른 해결책은 "-fvisibility = hidden"을 사용하지 않는 것입니다. 이는 컴파일러 및 링커의 경우 코드 성능의 손해를 입을 수 있습니다.

이전 답변은 정확하지만이 오류는 클래스의 객체에서 TypeID를 사용하려고 시도하여 발생할 수 있습니다. 아니요 가상 기능. C ++ RTTI는 vtable이 필요하므로 유형 식별을 수행하려는 클래스는 하나 이상의 가상 기능이 필요합니다.

가상 함수를 원하지 않는 클래스에서 유형 정보를 작동 시키려면 소멸자 가상으로 만드십시오.

RTTI 및 비 RTTI 라이브러리를 다루는 코드를위한 가능한 솔루션 :

a) -frtti 또는 -fno -rtti로 모든 것을 다시 컴파일하십시오
b) a)가 불가능한 경우 다음을 시도하십시오.

Libfoo가 RTTI없이 제작되었다고 가정합니다. 코드는 libfoo를 사용하고 RTTI로 컴파일합니다. 가상이있는 Libfoo에서 클래스 (FOO)를 사용하는 경우, 클래스 FOO 용 TypeInfo가 누락 된 링크 시간 오류가 발생할 수 있습니다.

가상이없는 다른 클래스 (예 : fooadapter)를 정의하고 사용하는 FOO로 전화를 전달합니다.

RTTI를 사용하지 않고 libfoo 기호에만 의존하는 작은 정적 라이브러리에서 fooadapter를 컴파일합니다. 헤더를 제공하고 코드 (RTTI를 사용하는) 대신 사용하십시오. Fooadapter에는 가상 기능이 없으므로 TypeInfo가 없으며 이진을 연결할 수 있습니다. Libfoo와 다른 클래스를 많이 사용하는 경우이 솔루션은 편리하지는 않지만 시작입니다.

나는이 오류에 대해 몇 시간을 보냈고, 여기서 다른 답변은 무슨 일이 일어나고 있는지 이해하는 데 도움이되었지만 내 특정 문제를 해결하지 못했습니다.

나는 두 가지를 사용하여 컴파일하는 프로젝트를 진행하고 있습니다. clang++ 그리고 g++. 나는 연결 문제를 사용하지 않았다 clang++, 그러나 undefined reference to 'typeinfo for 오류 g++.

중요한 점 : 링크 순서가 중요합니다 g++. 링크하려는 라이브러리를 순서대로 나열하면 부정확 한 순서로 typeinfo 오류.

보다 이렇게 질문 링크 순서에 대한 자세한 내용은 gcc/g++.

위의 RTTI, No-RTTI 토론과 유사하게,이 문제는 Dynamic_cast를 사용하고 클래스 구현이 포함 된 객체 코드를 포함하지 않으면 발생할 수 있습니다.

Cygwin 에서이 문제를 해결 한 다음 코드를 Linux로 포팅했습니다. MAKE 파일, 디렉토리 구조 및 심지어 GCC 버전 (4.8.2)은 두 경우 모두 동일했지만 코드는 Cygwin에서 올바르게 연결되어 작동했지만 Linux에서 링크하지 못했습니다. Red Hat Cygwin은 객체 코드 연결 요구 사항을 피하는 컴파일러/링커 수정을 분명히 만들었습니다.

Linux Linker 오류 메시지는 Dynamic_cast 라인으로 올바르게 지시되었지만이 포럼의 이전 메시지로 인해 실제 문제가 아닌 객체 코드가 누락 된 기능 구현이 누락되어 있습니다. 내 해결 방법은 Dynamic_cast를 사용하는 대신 기본 및 파생 클래스에서 가상 유형 기능을 대체하는 것이 었습니다. 이 기술은 Dynamic_cast가 올바르게 작동하도록 객체 구현 코드를 연결 해야하는 요구 사항을 피합니다.

기본 클래스 (추상 기본 클래스)에서 당신은 가상 소멸자를 선언하고 순수한 가상 함수로 소멸자를 선언 할 수 없으므로, 초록 클래스에서 바로 여기를 정의해야합니다. ) {}는 또는 파생 된 클래스에서 수행합니다.

이 작업을 수행하지 않으면 링크 시간에 "정의되지 않은 기호"가됩니다. VMT는 파생 클래스의 구현에 따라 테이블을 업데이트 할 때 널이 일치하는 모든 순수한 가상 함수에 대한 항목을 가지고 있기 때문에. 그러나 비 푸시이지만 가상 함수의 경우 VMT 테이블을 업데이트 할 수 있도록 링크 시간의 정의가 필요합니다.

C ++ Filt를 사용하여 기호를 demangle합니다. $ C ++ FILT _ZTIN10STORAGEAPI8BASEHOSTE와 마찬가지로 "StorageApi :: BaseHost의 TypeInfo"와 같은 것을 출력합니다.

지금 당장이 오류가 많이 있습니다. 일어난 일은 헤더 파일 전용 클래스를 헤더 파일과 CPP 파일로 분할 한 것입니다. 그러나 빌드 시스템을 업데이트하지 않았으므로 CPP 파일이 컴파일되지 않았습니다. 단순히 헤더에 선언 된 함수에 대한 정의되지 않은 참조 중 하나는 구현되지 않았으며, 이러한 TypeInfo 오류가 많이 있습니다.

솔루션은 빌드 시스템을 다시 실행하여 새 CPP 파일을 컴파일하고 연결하는 것이 었습니다.

제 경우에는 헤더 파일 및 파일이있는 타사 라이브러리를 사용했습니다. 하위 클래스를 서브 클래스하고 서브 클래스를 인스턴스화하려고 할 때 이와 같은 링크 오류가 발생했습니다.

@Sergiy가 언급했듯이 'RTTI'의 문제가 될 수 있음을 알 수 있듯이, 나는 그것을 해결했습니다. 생성자 구현을 별도의 .cpp 파일에 넣고 '-fno-rtti'플래그를 파일에 적용하십시오.. 잘 작동한다.

이 링크 오류의 내부에 대해 여전히 명확하지 않기 때문에 솔루션이 일반인지 확실하지 않습니다. 그러나 @francois가 언급 한 것처럼 어댑터 방식을 시도하기 전에 촬영할 가치가 있다고 생각합니다. 물론 모든 소스 코드를 사용할 수있는 경우 (내 경우가 아닌) 가능하면 '-frtti'와 함께 컴파일하는 것이 좋습니다.

내 솔루션을 시도하기로 선택한 경우 별도의 파일을 가능한 한 간단하게 만들고 C ++의 멋진 기능을 사용하지 마십시오. 관련된 것들에 특별한주의를 기울이고, 그 중 많은 부분이 RTTI에 따라 다릅니다.

내 인터페이스 (모든 순수한 가상 함수)가 하나 더 기능이 필요했을 때 동일한 오류가 발생했으며 "Null"을 잊어 버렸습니다.

나는 가지고 있었다

class ICommProvider { public: /** * @brief If connection is established, it sends the message into the server. * @param[in] msg - message to be send * @return 0 if success, error otherwise */ virtual int vaSend(const std::string &msg) = 0; /** * @brief If connection is established, it is waiting will server response back. * @param[out] msg is the message received from server * @return 0 if success, error otherwise */ virtual int vaReceive(std::string &msg) = 0; virtual int vaSendRaw(const char *buff, int bufflen) = 0; virtual int vaReceiveRaw(char *buff, int bufflen) = 0; /** * @bief Closes current connection (if needed) after serving * @return 0 if success, error otherwise */ virtual int vaClose(); };

Last Vaclose는 가상이 아니므로 컴파일 된 것은 어디에서 구현할 수 있는지 알지 못하여 혼란 스러웠습니다. 내 메시지는 다음과 같습니다.

... tcpclient.o :(. Rodata+0x38) :`icommprovider를위한 typeinfo '에 대한 정의되지 않은 참조

간단한 변화

virtual int vaClose();

에게

virtual int vaClose() = 0;

문제를 해결했습니다. 도움이되기를 바랍니다

나는 드문 상황에 직면하지만 이것은 비슷한 상황에서 다른 친구들을 도울 수 있습니다. GCC 4.4.7을 사용하여 이전 시스템에서 작업해야합니다. C ++ 11 이상의 지원으로 코드를 컴파일해야하므로 최신 버전의 GCC 5.3.0을 구축합니다. 코드를 구축하고 종속성에 링크 할 때 의존성이 이전 컴파일러로 빌드되면 '오류에 대한 정의 된 참조'를 얻었습니다. 부스트 및 CMAKE와 함께 빌드와 같은 일부 패키지는 일반적으로 구형 컴파일러를 사용하는 경향이 있으므로 일반적으로 그러한 문제를 일으 킵니다. 그들이 새로운 컴파일러를 사용하기 위해 먼 길을 가야합니다.

제 경우에는 Dynamic_cast 호출이 있더라도 순전히 라이브러리 종속성 문제입니다. Makefile에 충분한 의존성을 추가 한 후이 문제는 사라졌습니다.

의존성이없이 컴파일되었는지 확인하십시오 -f-nortti.

일부 프로젝트의 경우 rocksdb에서와 같이 명시 적으로 설정해야합니다.

USE_RTTI=1 make shared_lib -j4
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top