【问题标题】:LNK2019 unresolved error for inline functionLNK2019 内联函数未解决的错误
【发布时间】:2012-01-26 13:23:25
【问题描述】:

我不知道为什么会这样。我得到的错误如下:

Error   2   error LNK2019: unresolved external symbol "public: int __thiscall Graphics::GLMatrix::getColumnSize(void)" (?getColumnSize@GLMatrix@Graphics@@QAEHXZ) referenced in function _SDL_main  C:\Users\holland\Documents\code\c++\projects\OpenGL_01\OpenGL_01\main.obj
Error   3   error LNK2019: unresolved external symbol "public: int __thiscall Graphics::GLMatrix::getRowSize(void)" (?getRowSize@GLMatrix@Graphics@@QAEHXZ) referenced in function _SDL_main    C:\Users\holland\Documents\code\c++\projects\OpenGL_01\OpenGL_01\main.obj
Error   4   error LNK1120: 2 unresolved externals   C:\Users\holland\Documents\code\c++\projects\OpenGL_01\Debug\OpenGL_01.exe  

未链接的是我的 Matrix 类中的 getRowSize()getColumnSize() 函数。我做错了什么?

那么,我在这里做错了什么?我一直在寻找...寻找各种方式。

守则

头文件:

#ifndef GLMATRIX_H
#define GLMATRIX_H

#pragma once

#include <array>


namespace Graphics {

    class GLMatrix
    {
    public:
        GLMatrix(int sizeX, int sizeY);
        ~GLMatrix();
        void allocMatrix();
        void addColumnI(int row, int column, long item);
        void revertRowsByColumns(); /*changes the formula of r * c to c * r*/
        GLMatrix &operator *(float scalar); /*multiply by scalar*/
        inline int getRowSize();
        inline int getColumnSize();
    private:
        int _sizeX, _sizeY;
        long** _pArray;
    };

}

#endif //GLMATRIX_H

来源:

#include "GLMatrix.h"

namespace Graphics {

    GLMatrix::GLMatrix(int sizeX, int sizeY)
    {
        _sizeX = sizeX; 
        _sizeY = sizeY;
    }

    GLMatrix::~GLMatrix()
    {
        delete _pArray;
    }

    void GLMatrix::addColumnI(int row, int column, long item) {

    }

    inline int GLMatrix::getRowSize() {
        return _sizeX;
    }

    inline int GLMatrix::getColumnSize() {
        return _sizeY;
    }

    void GLMatrix::allocMatrix() {

        _pArray = new long*[_sizeX];

        for (int i = 0; i < _sizeX; ++i) {          
            _pArray[i] = new long[_sizeY];
        }

    }

    void GLMatrix::revertRowsByColumns() {

        long** columns = new long*[_sizeY];

        for (int col = 0; col < _sizeY; ++col) {
            columns[col] = new long[_sizeX];
            memmove(
                columns + col, 
                _pArray[_sizeX - col], 
                sizeof(_sizeX) - sizeof(col)
            );
        }   
    }

}

主要:

#include <SDL.h>
#include "GLMatrix.h"


int main(int argc, char* argv[]) {

    //SDL_Init(SDL_INIT_EVERYTHING);

    //matrix test

    Graphics::GLMatrix* matrix = new Graphics::GLMatrix(3, 3);

    int num_rows = matrix->getRowSize();
    int num_columns = matrix->getColumnSize();
    for (int row = 0; row < num_rows; ++row) {

    }

    //SDL_Quit();

    delete matrix;

    return 0;
}

【问题讨论】:

    标签: visual-c++ linker compiler-errors unresolved-external


    【解决方案1】:

    内联函数必须在头文件中声明的常识不再正确。几年以来,大多数编译器都实现了一种称为链接时间优化 (gcc) 或链接时间代码生成 (VC) 的功能,它保存有关内联函数(以及其他)的重要信息,允许链接器将所有目标文件视为“一个大快乐翻译单位”。因此,链接器可以内联您放入 cpp 文件中的函数。

    相关链接: http://msdn.microsoft.com/en-us/library/xbf3tbeh.aspx http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html(搜索-flto)

    编辑:从我之前写的内容中显然无法理解。此功能并非旨在使懒惰的程序员免于在每个翻译单元中声明内联函数。但它确实为您提供了可能导致问题的副产品。 一定要在头文件中声明内联函数。

    【讨论】:

    • -1。您声称内联函数不需要在标题中是正确的,但如果它们不在标题中,则它们需要在每个翻译单元中。链接时优化/代码生成不是获得每个翻译单元定义的方法,因为它使程序的标准一致性依赖于编译器选项而不是代码。内联函数需要在每个翻译单元中单独定义或在头文件中内联定义。
    • 感谢您的澄清!但我觉得你混淆了必须和应该。在这种情况下,我们不应该依赖编译器选项,但它确实有效,并且需要您了解此功能(这就是我最初遇到此问题的方式)。
    • 不,我不会混淆必须和应该,但我认为你会。我们绝不能依赖链接时间优化来获得有效的函数定义。一个程序在翻译单元(它被用于)中缺少内联函数的定义是不合格的。因此,即使 LTO/LTCG 使其工作,它仍然是错误的,因为如果您依赖这种行为,您甚至可能无法在没有 LTO/LTCG 的情况下编译程序。所以不要这样做。
    • 好吧,很公平 :) 当然,我从不这样做,这就是我在帖子编辑中写的。
    【解决方案2】:

    内联函数必须在头文件中定义。 (更具体地说,定义必须在使用它的每个翻译单元中可见。)

    【讨论】:

    • 通俗地说,一个翻译单元是一个单一的 C++ 文件和它所包含的所有文件
    • 对于傻瓜:无论你有什么头文件,你永远永远永远都不会在一个 .cpp 文件中放置一个内联函数并从另一个 .cpp 文件中调用它。内联函数必须与调用它们位于同一个 .cpp 文件中,或者位于 .h 文件中的某个位置。如果你不这样做,你将花费 4 个小时调试链接器错误而没有成功。请务必阅读parashift.com/c++-faq-lite/inline-functions.html
    【解决方案3】:

    1。翻译单元是单个源文件(在您的情况下为“源”和“主”)以及包含的文件。

    2。内联函数

    C++11,§3.2/3

    "[...] 内联函数应在使用 odr 的每个翻译单元中定义。[...]"

    § 7.1.2/4

    内联函数应在使用它的每个翻译单元中定义,并且在每种情况下都应具有完全相同的定义(3.2)。 [...]

    您的“来源”翻译单元有getRowSizegetColumnSize 的定义。您的“主要”翻译单元没有!这是未定义的行为,因为编译器不需要检查。

    LTCG/LTO

    弗拉基米尔的部分答案是正确的。有链接时间优化(或链接时间代码生成)。但它并不能帮助懒惰的程序员为内联函数保存函数定义。

    LTCG/LTO 是为了让编译器立即看到所有函数,而编译器又可能决定内联在正常情况下不可见的函数。声明为inline 的函数必须在编译器使用它们的每个点上每个定义都可见。因此,LTCG/LTO 不需要(也不应被滥用于)解决缺少的内联链接错误。


    只是为了澄清一点:我很清楚这是一个老问题,但它还没有得到正确的回答,我只是摔倒了。

    【讨论】:

      【解决方案4】:

      我还遇到了 Visual Studio 2019 库中内联函数的链接错误问题。我在 C/C++ 属性的选项卡语言中将属性“删除未引用的代码和数据”设置为“否”并解决了链接错误。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-11-13
        • 2014-05-12
        • 2014-05-14
        • 1970-01-01
        • 1970-01-01
        • 2013-01-31
        • 2015-01-11
        相关资源
        最近更新 更多