0

我已经在http://www.cplusplus.com/forum/general/96128/上问过这个问题,但无济于事。

是否有人在 g++ 4.2 中遇到过同样的错误:internal compiler error: in make_thunk, at cp/method.c:129

我认为没有必要包含示例代码。相应的代码在其他几个较新的 g++ 版本以及 clang++ 上编译时不会出现警告和错误。这是正确的,并且在 GCC 的 bugzilla 中提到了该错误(甚至多次,因为它似乎经常重复出现),但没有提供解决方法。

请不要告诉也使用更新的 g++。我必须在 Ubuntu Hardy 附带的 g++ 上编译它,所以我无法更改编译器。主要开发是在 Ubuntu Precise 上完成的,但我需要让它与 Hardy 兼容。

我不知道 thunk 应该是什么,我只怀疑它与协变和/或多重继承有关。此外,我还有几个类似的结构化头文件,它们都编译得很好,尽管唯一的变化是名称是类的名称,我没有目标,因为 Hardy 上的编译器错误而改变它。

另一个事实是,它发生在包含时间。

In file included from /home/heiko/hgl/src/compiler/compilerprojectfactory.cpp:18:
/home/heiko/hgl/src/compiler/compilertype.h: In instantiation of 'HGL::Compiler::CompilerType<HGL::Vector2D, HGL::Compiler::CompilerBase>':
/home/heiko/hgl/src/compiler/compilervector2d.h:23: instantiated from here
/home/heiko/hgl/src/compiler/compilertype.h:22: internal compiler error: in make_thunk, at cp/method.c:129
Please submit a full bug report,
with preprocessed source if appropriate.
See <URL:http://gcc.gnu.org/bugs.html> for instructions.
For Debian GNU/Linux specific bug reporting instructions,
see <URL:file:///usr/share/doc/gcc-4.2/README.Bug

编辑:这里是导致错误的标题:

#include "compilertype.h"
#include "vector2d.h"

namespace HGL {

class Vector2D;

namespace Compiler {

/**
    @author Heiko Schäfer <heiko@rangun.de>
*/
class _LOCAL Vector2D : public Compiler::CompilerType<HGL::Vector2D> {
    DISALLOW_COPY_AND_ASSIGN(Vector2D)
public:
    Vector2D(float x, float y, int line);

    using IType::operator=;

    virtual operator HGL::Vector2D &() const throw(InvalidExpressionException);
protected:
    virtual ~Vector2D();

    void append(ISerializeable::BUFFER *dest, const HGL::IType *type) const;
};

}

}

这里的模板:

#include "compilerbase.h"
#include "iproject.h"
#include "util.h"

namespace HGL {

namespace Compiler {

const IProject::VSTRUCT minReq = { HGL_MINREQ_MAJOR, HGL_MINREQ_MAJOR, HGL_MINREQ_MAJOR };

template<class Type, class Base = CompilerBase>
class _LOCAL CompilerType : public Type, public Base {
    DISALLOW_COPY_AND_ASSIGN(CompilerType)
public:
    using IType::operator=;

    template<class Param>
    inline CompilerType(const Param &p, bool b, int line,
                        const IProject::VSTRUCT &vs = IProject::VSTRUCT()) :
        Type(p), Base(line, b) {
        init(vs);
    }

    template<class Param>
    inline CompilerType(const Param &p, int line,
                        const IProject::VSTRUCT &vs = IProject::VSTRUCT()) : Type(p), Base(line) {
        init(vs);
    }

    inline CompilerType(bool b, int line, const IProject::VSTRUCT &vs = IProject::VSTRUCT())
        : Type(), Base(line, b) {
        init(vs);
    }

    template<class Param1, class Param2>
    inline CompilerType(const Param1 &p1, const Param2 &p2, int line,
                        const IProject::VSTRUCT &vs = IProject::VSTRUCT()) :
        Type(p1, p2), Base(line) {
        init(vs);
    }

    template<class Param1, class Param2>
    inline CompilerType(const Param1 &p1, const Param2 &p2, bool b, int line,
                        const IProject::VSTRUCT &vs = IProject::VSTRUCT()) : Type(p1, p2),
        Base(line, b) {
        init(vs);
    }

    inline CompilerType(int line,
                        const IProject::VSTRUCT &vs = IProject::VSTRUCT()) : Type(), Base(line) {
        init(vs);
    }

    inline virtual void append(ISerializeable::BUFFER *dest, const IType *type) const {
        Base::append(dest, type);
    }

protected:
    inline virtual ~CompilerType() {}

    inline virtual void init(const IProject::VSTRUCT &vs) {
        const_cast<IProject::VSTRUCT &>(vs) = std::max(vs, minReq);
        CompilerBase::setMinRequiredVersion(vs, Type::getSerialID());
    }

};

}

}

解决!

在挖掘 g++ 4.2 的源代码后,我发现它现在需要完整树中的所有类型。g++ > 4.2 显然不需要这个。

因此,错误出现在一个相关类中,该类具有一个具有转发专业化的模板成员。我只是包含了标题而不是转发,g++ 4.2 很高兴。

否则,不给出错误确实是一个不好的错误,但是这个无用的消息。

4

1 回答 1

1

thunktrampoline是在动态调度的某些实现中添加的一段代码,以根据正在使用的最终覆盖器调整基本虚函数的接口。正如您所提到的,通常需要this在多重/虚拟继承中调整指针(对于在第一个非空继承之后列出的基),并使用协变返回类型调整生成的指针/引用。

该错误表明它是一个编译器错误。如果您必须使用该特定编译器,您将需要解决该问题,这将涉及更改您的设计。您可以尝试限制多重/虚拟继承的使用,重新排序列表中的基数或尝试玩弄直到您设法让编译器以某种方式消化该代码。如果在为协变返回类型生成适配器时出现问题,请考虑删除协变返回并提供将返回协变类型的重载(使用不同的名称)(即用返回最多的非虚函数替换协变返回派生类型和一个调用前一个并返回对基类的引用的虚函数)。

除了那些通用提示之外,没有看到您拥有的代码和编译器的实现,没有什么可说的。

于 2013-03-18T19:13:42.490 回答