Cocos2d-x 3.x 版本关于PDB错误,编译时间过长,编译内存消耗过大的解决方法

最近把之前的项目升级到了 Cocos2d-x 3.17.2版本,在解决了一系列的问题之后,编译时报错:

error C3130: Internal Compiler Error: failed to write injected code block to PDB

碰到这个之后,我搜索了一下,基本上所有人给出的方案都是将编译选项中关于调试信息生成,换成C7兼容,这样就可以继续编译。

我尝试了一下,将工程的调试信息换成了C7兼容,能顺利运行,但是编译的时间非常的长(每一次链接都需要10分钟以上),而且,链接器的内存消耗最高峰值达到了6G,这个明显存在一些没解决的问题。在尝试几次之后,我取消了C7兼容,换回了之前的模式。

重新观察了产生C3130错误的地方,发现这些错误都是集中在clone这个函数,都是在clone这个地方报错。只要是继承了Clonable接口的子类,都有这个问题,进一步的分析,找到了错误的真实原因:

/** 
  * Interface that defines how to clone an Ref.
  * @lua NA
  * @js NA
  */
class CC_DLL Clonable
{
public:
    /** Returns a copy of the Ref. */
    virtual Clonable* clone() const = 0;
    
    /**
     * @js NA
     * @lua NA
     */
    virtual ~Clonable() {};

    /** Returns a copy of the Ref.
     * @deprecated Use clone() instead.
     */
    CC_DEPRECATED_ATTRIBUTE Ref* copy() const
    {
        // use "clone" instead
        CC_ASSERT(false);
        return nullptr;
    }
};

注意这个代码,在Clonable基类中,返回值是 Clonable * , 然后在它的派生类中,返回值变了:

     * @return A clone action.
     */
    virtual Action* clone() const
    {
        CC_ASSERT(0);
        return nullptr;
    }

变成了Action *,由于C++对函数的识别只基于函数名和输入参数,不会识别返回值,因此,在继承的时候,这种写法是允许的,VC内部怎么实现,我不清楚,但是,我猜测应该是给每一个派生类,生成多个clone函数,相同的代码来对应不同的返回值,但这样会导致一个问题,如果派生链过长,会让编译生成代码成倍增加。

Clonable 这个类,仅仅是一个接口约定,整个工程基本上不会用到Clonable这个层级,于是,我取消了 Action 类派生于Clonable接口:

/** 
 * @brief Base class for Action objects.
 */
class CC_DLL Action : public Ref //, public Clonable
{
public:

找到CCAction这个头文件,把 public Clonable注释掉。

接下来,重新编译整个工程,再也没有C3130错误,而且链接时间大大缩短(2分钟以内),生成的PDB也从之前的400多MB,降低到96MB,内存的消耗,最高3个G多一些。

 

这个只是临时的解决方案,虽然不影响代码执行,但还是破坏了Cocos2d-x的派生体系结构,而且仅仅解决了Action类,还有很多其他的类没处理,所以PDB也没有缩减到理想大小。所以,解决方式还是很 Ugly。

最佳的解决方案,是重新设计 Clonable 的体系,每一个派生类都使用标准的 Clonable * clone() const 函数定义,写一个宏或则模板函数来转换成对应的类。但这样做就是对工程的深度定制,而且以后更新版本也会有麻烦。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值