programing

typeinfo에 대한 g ++ 정의되지 않은 참조

new-time 2020. 5. 12. 22:19
반응형

typeinfo에 대한 g ++ 정의되지 않은 참조


방금 다음 오류가 발생했습니다 (온라인에서 솔루션을 찾았지만 스택 오버플로에는 표시되지 않음).

(.gnu.linkonce. [stuff]) : [method] [object file] :(. gnu.linkonce. [stuff])에 대한 정의되지 않은 참조 : [classname]의 typeinfo에 대한 정의되지 않은 참조

왜 "typeinfo에 대한 정의되지 않은 참조"링커 오류 중 하나가 발생합니까?(뒤에서 일어나는 일을 설명 할 수 있다면 보너스 포인트.)


가능한 한 가지 이유는 가상 함수를 정의하지 않고 선언했기 때문입니다.동일한 컴파일 단위로 정의하지 않고 선언하면 다른 위치에 정의되어 있음을 나타냅니다. 즉, 링커 단계는 다른 컴파일 단위 (또는 라이브러리) 중 하나에서 해당 링크를 찾으려고합니다.가상 기능을 정의하는 예는 다음과 같습니다.

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과 함께 작성됩니다. [...] 다른 모든 유형의 경우 type_info 객체를 사용할 때 다음과 같이 씁니다. 식에`typeid '를 적용 할 때, 객체를 던지거나 catch 절 또는 예외 사양의 유형을 참조합니다.

같은 페이지에서 조금 더 일찍

클래스가 인라인이 아닌 순수한 가상 함수를 선언하면 첫 번째 함수가 클래스의 "키 메소드"로 선택되고 vtable은 키 메소드가 정의 된 변환 단위에서만 생성됩니다.

따라서 다른 답변에서 이미 언급했듯이 "키 방법"에 정의가없는 경우이 오류가 발생합니다.


하나의 .so를 다른 .so에 연결하는 경우 또 다른 가능성은 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 누락)가 발생할 수 있습니다.가상이없고 사용중인 Foo로 통화를 전달하는 다른 클래스 (예 : FooAdapter)를 정의하십시오.RTTI를 사용하지 않고 libfoo 기호에만 의존하는 작은 정적 라이브러리에서 FooAdapter를 컴파일하십시오. 헤더를 제공하고 대신 RTTI를 사용하는 코드에서 사용하십시오. FooAdapter에는 가상 기능이 없으므로 typeinfo가 없으므로 바이너리를 연결할 수 있습니다. libfoo와 다른 클래스를 많이 사용하는 경우이 솔루션은 편리하지는 않지만 시작입니다.


I just spent a few hours on this error, and while the other answers here helped me understand what was going on, they did not fix my particular problem.

I am working on a project that compiles using both clang++ and g++. I was having no linking issues using clang++, but was getting the undefined reference to 'typeinfo for error with g++.

The important point: Linking order MATTERS with g++. If you list the libraries you want to link in an order which is incorrect you can get the typeinfo error.

See this SO question for more details on linking order with gcc/g++.


Similarly to the RTTI, NO-RTTI discussion above, this problem can also occur if you use dynamic_cast and fail to include the object code containing the class implementation.

I ran into this problem building on Cygwin and then porting code to Linux. The make files, directory structure and even the gcc versions (4.8.2) were identical in both cases, but the code linked and operated correctly on Cygwin but failed to link on Linux. Red Hat Cygwin has apparently made compiler/linker modifications that avoid the object code linking requirement.

The Linux linker error message properly directed me to the dynamic_cast line, but earlier messages in this forum had me looking for missing function implementations rather than the actual problem: missing object code. My workaround was to substitute a virtual type function in the base and derived class, e.g. virtual int isSpecialType(), rather than use dynamic_cast. This technique avoids the requirement to link object implementation code just to get dynamic_cast to work properly.


In the base class (an abstract base class) you declare a virtual destructor and as you cannot declare a destructor as a pure virtual function, either you have to define it right here in the abstract class, just a dummy definition like virtual ~base() { } will do, or in any of the derived class.

If you fail to do this, you will end up in an "undefined symbol" at link time. Since VMT has an entry for all the pure virtual functions with a matching NULL as it updates the table depending on the implementation in the derived class. But for the non-pure but virtual functions, it needs the definition at the link time so that it can update the VMT table.

Use c++filt to demangle the symbol. Like $c++filt _ZTIN10storageapi8BaseHostE will output something like "typeinfo for storageapi::BaseHost".


I got a lot of these errors just now. What happened is that I split a header-file-only class into a header file and a cpp file. However, I didn't update my build system, so the cpp file didn't get compiled. Among simply having undefined references to the functions declared in the header but not implemented, I got a lot of these typeinfo errors.

The solution was to re-run the build system to compile and link the new cpp file.


in my case, i used a third-party library with header files and so file. i subclassed one class, and link error like this occurred when i try to instantiate my subclass.

as mentioned by @sergiy, knowning it could be the problem of 'rtti', i managed to workaround it by put the constructor implementation into separate .cpp file and apply '-fno-rtti' compile flags to the file. it works well.

as i am still not quite clear about the internal of this link error, i am not sure whether my solution is general. however, i think it worth a shot before trying the adaptor way as mentioned by @francois . and of course, if all source codes are available(not in my case), better do recompile with '-frtti' if possible.

one more thing, if you choose to try my solution, try make the separate file as simple as possible, and do not use some fancy features of C++. take special attention on boost related things, cause much of it depends on rtti.


I've got same error when my interface (with all pure virtual functions) needed one more function and I forgot to "null" it.

I had

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 is not virtual so compiled did not know where to get implementation for it and thereby got confused. my message was:

...TCPClient.o:(.rodata+0x38): undefined reference to `typeinfo for ICommProvider'

Simple change from

virtual int vaClose();

to

virtual int vaClose() = 0;

fixed the problem. hope it helps


I encounter an situation that is rare, but this may help other friends in similar situation. I have to work on an older system with gcc 4.4.7. I have to compile code with c++11 or above support, so I build the latest version of gcc 5.3.0. When building my code and linking to the dependencies if the dependency is build with older compiler, then I got 'undefined reference to' error even though I clearly defined the linking path with -L/path/to/lib -llibname. Some packages such as boost and projects build with cmake usually has a tendency to use the older compiler, and they usually cause such problems. You have to go a long way to make sure they use the newer compiler.


In my case it is purely a library dependency issue even if I have dynamic_cast call. After adding enough dependency into makefile this problem was gone.


Check that your dependencies were compiled without -f-nortti.

For some projects you have to set it explicitly, like in RocksDB:

USE_RTTI=1 make shared_lib -j4

참고URL : https://stackoverflow.com/questions/307352/g-undefined-reference-to-typeinfo

반응형