【问题标题】:Code requires too much memory代码需要太多内存
【发布时间】:2023-04-09 14:29:01
【问题描述】:

我正在将一些代码移植到另一个结构中:

class EnvironObject
{
   protected:
      vector<float> mX, mY, mXSpeed, mYSpeed;
      int mMaxObjects;

   public:
      virtual void init(int maxObjects);
      virtual void setLimit(int limit);
      virtual int getLimit();
      virtual void update(float arg) = 0;
};

void EnvironObject::setLimit(int limit)
{
   mMaxObjects = limit;

   mX.resize(limit, 0); mY.resize(limit, 0);
   mXSpeed.resize(limit, 0); mY.resize(limit, 0);
}

int EnvironObject::getLimit()
{
   return mMaxObjects;
}

void EnvironObject::init(int maxObjects)
{
    mX = mY = mXSpeed = mYSpeed = std::vector<float>(mMaxObjects);

    fill(mX.begin(), mX.end(), 0);
    fill(mY.begin(), mY.end(), 0);
    fill(mXSpeed.begin(), mXSpeed.end(), 0);
    fill(mYSpeed.begin(), mYSpeed.end(), 0);

    /*mX.reserve(mMaxObjects * 1.5); mY.reserve(mMaxObjects * 1.5);
    mXSpeed.reserve(mMaxObjects * 1.5); mYSpeed.reserve(mMaxObjects * 1.5);*/

    mMaxObjects = maxObjects;
}

这是一些基本类,现在是用法:

class Rain : public EnvironObject
{
    public:
        Rain(int maxDrops = 150);
        void update(float windPower);
};

Rain::Rain(int maxDrops)
{
    srand(time(NULL));

    IEnvironObject::init(maxDrops);
}

void Rain::update(float windPower)
{
    for (int i=0; i < mMaxObjects; i++)
    {
       mX[i] += mXSpeed[i];
       mY[i] += mYSpeed[i];

       mXSpeed[i] += windPower;
       mYSpeed[i] += G;

   // Drawing
    }
}

Rain 使用默认构造函数创建的对象(因此,每个数组的大小为 150 个元素),然后我调用 setLimit(50)。 问题是代码几乎每次运行都会出现异常:

terminate called after throwing an instance of 'std::bad_alloc'

有时它会出现在线段错误:

mY[i] += mYSpeed[i];

我无法想象它会是什么,因为代码很旧并且可以正常工作。新的只是基类。

当我在启动应用程序时查看 RAM 使用情况时,我看到几乎 +600 mb!

【问题讨论】:

  • 您能否添加一个示例 main 函数来展示您如何调用/使用它们?从表面上看,我看不出有什么明显的错误……
  • init 函数是代码异味。这就是构造函数的用途。
  • @GMain 我可以从派生类调用基构造函数吗?因为编译器返回了一些关于这个的错误。
  • protected 数据成员也是一种代码味道:基类应该如何强制执行其不变量?

标签: c++ exception memory allocation


【解决方案1】:

再看看你的那个功能:

void EnvironObject::init(int maxObjects)
{
    mX = mY = mXSpeed = mYSpeed = std::vector<float>(mMaxObjects);
    //                                               ^
    // ...

    mMaxObjects = maxObjects;
}

您正在使用尚未初始化的变量。

你的班级的一个大问题是你正在做所谓的两阶段构建。您的类EnvironObject 有一个编译器提供的默认构造函数,它为所有POD 类型(mMaxObjects)创建一个具有随机值的对象。然后用户需要调用init() 方法来真正初始化对象。但这就是构造函数的用途!

void EnvironObject::EnvironObject(int maxObjects)
  : mMaxObjects(maxObjects)
  , mX(maxObjects), mY(maxObjects), mXSpeed(maxObjects), mYSpeed(maxObjects)
{
    /* these aren't necessary, std::vector automatically does this
    fill(mX.begin(), mX.end(), 0);
    fill(mY.begin(), mY.end(), 0);
    fill(mXSpeed.begin(), mXSpeed.end(), 0);
    fill(mYSpeed.begin(), mYSpeed.end(), 0);
    */
}

派生类可以使用这个构造函数:

Rain::Rain(int maxDrops)
 : EnvironObject(maxDrops)
{
    srand(time(NULL));
}

关于订阅mY[i] += mYSpeed[i]中的这次崩溃:

当您通过一个不指向任何地方的指针调用此函数时,可能会发生这种情况。

【讨论】:

  • 顺便说一句,删除 4 个数组并使用该字段构建结构会更好。并制作带有结构的向量?
  • @Ockonal:是的,这当然更好(虽然在内存方面并不多),否则到目前为止它不会被投票。 (顺便说一句,我也对 Reinderien 的回答投了赞成票。)
【解决方案2】:

在初始化之前,您在 init() 中使用 mMaxObjects。所以它有一个随机值。

void EnvironObject::init(int maxObjects) 
{ 
   mX = mY = mXSpeed = mYSpeed = std::vector<float>(mMaxObjects);  // you mean maxObjects here

【讨论】:

    【解决方案3】:

    我想你想替换

    void EnvironObject::init(int maxObjects)
    {
        mX = mY = mXSpeed = mYSpeed = std::vector<float>(mMaxObjects);
    

    void EnvironObject::init(int maxObjects)
    {
        mX = mY = mXSpeed = mYSpeed = std::vector<float>(maxObjects);
    

    注意在向量创建中将 mMaxObject 替换为 maxObjects。

    【讨论】:

      【解决方案4】:

      有一条评论,虽然它不太可能修复您的内存错误,但由于字段 mX、mY、mXSpeed 和 mYSpeed 似乎相关并且向量的大小都相同,您应该考虑将它们合并到一个结构中四个成员,并且有一个包含多个结构实例的向量。

      【讨论】:

      • 这实际上取决于,如果您打算一次处理一个字段,则将各个字段分开是有意义的,这样您就不会用您不关心的值填充缓存。虽然不记得这个编程策略的名称......
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-06
      • 2013-01-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多