GCC C ++ 링커 오류 : 'vtable for XXX'에 대한 정의되지 않은 참조, 'ClassName :: ClassName ()'에 대한 정의되지 않은 참조
Eclipse-CDT를 사용하여 Ubuntu x64에서 C ++ 프로젝트를 설정하고 있습니다. 저는 기본적으로 hello world를하고 있으며 상용 타사 라이브러리에 연결합니다.
라이브러리에 연결된 헤더 파일을 포함했지만 여전히 링커 오류가 발생합니다. 여기에 명백한 것 이외의 가능한 문제가 있습니까 (예 : 올바른 라이브러리에 연결하고 있다고 99 % 확신합니다).
- 링크하는 정적 라이브러리가 64 비트인지 확인하는 방법이 있습니까?
- 라이브러리에 내가 가질 것으로 예상하는 클래스 (및 메서드)가 있는지 확인하는 방법이 있습니까?
Eclipse 말한다 :
건물 대상 : LinkProblem 호출 : GCC C ++ 링커 g ++ -L / home / notroot / workspace / somelib-3 / somelib / target / bin -o "LinkProblem"./src/LinkProblem.o -lsomelib1 -lpthread -lsomelib2 -lsomelib3 ./src/LinkProblem.o :`main '함수에서 : /home/notroot/workspace/LinkProblem/Debug/../src/LinkProblem.cpp:17 :`SomeClass :: close () '에 대한 정의되지 않은 참조 ./src/LinkProblem.o :`SomeOtherClass '함수에서 : /home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:148 :`SomeClass :: SomeClass () '에 대한 정의되지 않은 참조 /home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:148 :`Vtable for SomeOtherClass '에 대한 정의되지 않은 참조 /home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:151 :`SomeClass :: ~ SomeClass () '에 대한 정의되지 않은 참조 ./src/LinkProblem.o :`~ SomeOtherClass '함수에서 : /home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:140 :`Vtable for SomeOtherClass '에 대한 정의되지 않은 참조 /home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:140 :`SomeClass :: ~ SomeClass () '에 대한 정의되지 않은 참조 /home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:140 :`SomeClass :: ~ SomeClass () '에 대한 정의되지 않은 참조 collect2 : ld가 1 종료 상태를 리턴했습니다. make : *** [LinkProblem] 오류 1
이러한 메소드가 라이브러리 중 하나에 있다고 가정하면 순서 문제처럼 보입니다.
라이브러리를 실행 파일에 연결할 때 선언 된 순서대로 수행됩니다.
또한 링커는 현재 해결되지 않은 종속성을 해결하는 데 필요한 메서드 / 함수 만 사용합니다. 후속 라이브러리가 원래 개체에 필요하지 않은 메서드 / 함수를 사용하면 종속성이 누락됩니다.
작동 원리 :
- 모든 개체 파일을 가져 와서 실행 파일로 결합합니다.
- 오브젝트 파일 간의 종속성을 해결하십시오.
- 각 라이브러리 순서대로 :
- 해결되지 않은 종속성을 확인하고 lib가이를 해결하는지 확인하십시오.
- 그렇다면 필요한 부분을 실행 파일에로드하십시오.
예:
개체에는 다음이 필요합니다.
- 열다
- 닫기
- BatchRead
- BatchWrite
Lib 1은 다음을 제공합니다.
- 열다
- 닫기
- 읽다
- 쓰다
Lib 2는
- BatchRead (그러나 lib1 : read 사용)
- BatchWrite (그러나 lib1 : write 사용)
다음과 같이 연결된 경우 :
gcc -o plop plop.o -l1 -l2
그러면 링커가 읽기 및 쓰기 기호를 확인하지 못합니다.
그러나 다음과 같이 응용 프로그램을 연결하면 :
gcc -o plop plop.o -l2 -l1
그러면 올바르게 연결됩니다. l2는 BatchRead 및 BatchWrite 종속성을 해결하지만 두 개의 새로운 종속성 (읽기 및 쓰기)도 추가합니다. l1과 연결하면 다음 네 가지 종속성이 모두 해결됩니다.
이 링커 오류는 일반적으로 (내 경험상) 선언으로 자식 클래스의 가상 함수를 재정의했지만 메서드에 대한 정의를 제공하지 않았 음을 의미합니다. 예를 들면 :
class Base
{
virtual void f() = 0;
}
class Derived : public Base
{
void f();
}
그러나 당신은 f의 정의를주지 않았습니다. 클래스를 사용하면 링커 오류가 발생합니다. 일반적인 링커 오류와 마찬가지로 컴파일러가 사용자가 말하는 내용을 알고 있었지만 링커가 정의를 찾을 수 없기 때문입니다. 이해하기 매우 어려운 메시지입니다.
Qt C ++는 클래스를 변경하여 이제 QObject에서 상속하도록 (즉, 신호 / 슬롯을 사용할 수 있도록)이 오류를 표시합니다. qmake -r을 실행하면 moc가 호출되고이 문제가 해결됩니다.
어떤 종류의 버전 제어를 통해 다른 사람과 작업하는 경우 .pro 파일을 변경하는 것이 좋습니다 (예 : 빈 줄 추가 / 제거). 다른 모든 사람이 변경 사항을 가져 와서 make를 실행하면 make는 .pro 파일이 변경되었음을 확인하고 자동으로 qmake를 실행합니다. 이것은 팀원들이 당신의 좌절감을 되풀이하는 것을 막을 것입니다.
나에게 문제는 꽤 모호한 것으로 판명되었습니다. 내 수업은 다음과 같습니다.
//-----------------------------------------
// libbase.h
class base {
public:
base() { }
virtual ~base() { }
virtual int foo() { return 0; }
};
//-----------------------------------------
//-----------------------------------------
// libbase.cpp
#include "libbase.h"
//-----------------------------------------
//-----------------------------------------
// main.h
class derived : public base {
public:
virtual int foo() ;
};
//-----------------------------------------
//-----------------------------------------
// main.cpp
int main () {
derived d;
}
//-----------------------------------------
링커에 문제가 있습니다. 내 헤더 파일은 어딘가의 라이브러리에 있었지만 모든 가상 함수는 클래스 선언에서 '인라인'으로 선언되었습니다. (아직) 가상 함수를 사용하는 코드가 없었기 때문에 컴파일러 나 링커는 실제 함수 본문을 제자리에 두지 않았습니다. 또한 vtable을 생성하지 못했습니다.
In my main code where I derived from this class, the linker tried to connect my class to the base class and his vtable. But the vtable had been discarded.
The solution was to declare at least one of the virtual functions' bodies outside the class declaration, like this:
//-----------------------------------------
// libbase.h
class base {
public:
base() { }
virtual ~base() ; //-- No longer declared 'inline'
virtual int foo() { return 0; }
};
//-----------------------------------------
//-----------------------------------------
// libbase.cpp
#include "libbase.h"
base::~base()
{
}
//-----------------------------------------
In regards to problems with Qt4, I couldn't use the qmake moc option mentioned above. But that wasn't the problem anyway. I had the following code in the class definition:
class ScreenWidget : public QGLWidget
{
Q_OBJECT // must include this if you use Qt signals/slots
...
};
I had to remove the line "Q_OBJECT" because I had no signals or slots defined.
I had this error message. The problem was that I declared a virtual destructor in the header file, but the virtual functions' body was actually not implemented.
This error will also occur when we simply declare a virtual function without any definition in the base class.
For example:
class Base
{
virtual void method1(); // throws undefined reference error.
}
Change the above declaration to the below one, it will work fine.
class Base
{
virtual void method1()
{
}
}
In my case the problem occured when i forgot to add the =0 on one function in my pure virtual class. It was fixed when the =0 was added. The same as for Frank above.
class ISettings
{
public:
virtual ~ISettings() {};
virtual void OKFunction() =0;
virtual void ProblemFunction(); // missing =0
};
class Settings : ISettings
{
virtual ~Settings() {};
void OKFunction();
void ProblemFunction();
};
void Settings::OKFunction()
{
//stuff
}
void Settings::ProblemFunction()
{
//stuff
}
I stumbled across the issue now, too. The application defined a pure virtual interface class and a user-defined class provided through a shared lib was supposed to implement the interface. When linking the application, the linker complained that the shared lib would not provide vtable and type_info for the base class, nor could they be found anywhere else. Turned out that I simply forgot to make one of the interface's methods pure virtual (i.e. omitted the " = 0" at the end of the declaration. Very rudimentary, still easy to overlook and puzzling if you can't connect the linker diagnostic to the root cause.
I had this error message when trying "hello world" like things with Qt. The problems went away by correctly running the qt moc (meta object compiler) and compiling+including these moc-generated files correctly.
If you have a base class with pure virtual function, make sure your base class constructor and destructor has body otherwise linker fails.
I put this for future visitors:
if you are receiving the error on creating an Exception
object, then the cause of it probably is a lack of definition for what()
virtual function.
'Development Tip' 카테고리의 다른 글
intelliJ IDEA 13 오류 : Android SDK를 선택하세요. (0) | 2020.10.30 |
---|---|
Android에서 흔들림 / 흔들림보기 애니메이션 (0) | 2020.10.30 |
Python을 사용하여 plt.show () 창을 최대화하는 방법 (0) | 2020.10.30 |
Android에서 툴바 뒤로 버튼의 색상을 변경하는 방법은 무엇입니까? (0) | 2020.10.30 |
Android는 gridlayoutmanager를 사용하여 recyclerview의 마지막 요소 아래에 간격을 추가합니다. (0) | 2020.10.30 |