【问题标题】:C++ vector of struct with vector in struct causing exception结构的 C++ 向量与结构中的向量导致异常
【发布时间】:2012-10-16 23:16:20
【问题描述】:

我遇到了以下代码的问题,几个小时以来我都无法解决... 我很高兴有任何建议。

类型定义如下:

typedef std::vector< cv::RotatedRect > ds_t;

typedef struct id_ {
std::string path;
std::string fileName;
} id_t;

typedef struct dd_ {
    cv::RotatedRect bB;
} dd_t;

typedef std::pair<id_t, std::vector<dd_t> > ts_t;

typedef std::vector<ts_t> tss_t;

然后我尝试用数据填充类型:

tss_t samples
while (readdir(pDir) != NULL) {
     ts_t sample;
     sample.first.path = _path;
     sample.first.fileName = _name;
     ds_t detections;
     getDetections(_path, detections); //this only filles the detecions byref
     for(size_t i=0; i<detections.size(); i++) {
         dd_t data;
         data.bB = detections[i];
         sample.second.push_back(data); //TODO FIXME
     }
     samples.push_back(sample);
 }

cv::RotatedRect 是一个非常基础的类。

class RotatedRect{
   public:
   RotatedRect();
   RotatedRect(const Point2f& _center, const Size2f& _size, float _angle);
   void points(Point2f pts[]) const;

   Point2f center;
   Size2f size;
   float angle; 
};

bool getDetections(const std::string &imagePath, ds_t &detections)
{
  //some processing
  for(size_t i=0;i<5;i++)
    detections.push_back(RotatedRect(cv::Point2f(110.,110.), cv::Size2f(10.,10.), 90.0f));

  return true;
}

希望我复制了整个代码,我知道,我不需要大部分 typedef...

我已经尝试预留空间sample.second.reserve(detections.size()),但这只是将错误推迟到samples.push_back。

错误的行由 FIXME 指示,导致“在抛出 'std::bad_alloc' 的实例后调用终止”

提前感谢您的任何建议。

【问题讨论】:

  • 你在 WHILE 循环中循环了多少次?你确定 WHILE 循环不是无限循环吗?
  • 我在您发布的代码中看不到任何错误。也许您在getDetections() 中有堆损坏?
  • 除上述之外,在您的源代码中包含“简单”RotatedRect 类的定义。它的复制直接参与到您的循环中。
  • detections.size() 能有多大?
  • @WhozCraig 我检查了RotatedRect(OpenCV 的一部分),它只是一堆浮点数。那里没有错误。

标签: c++ stl vector struct


【解决方案1】:

std::bad_alloc 通常意味着你的内存已经用完了——可能是因为泄漏,或者只是因为你分配了太多。它也可能(很少)由于堆损坏(在分配的数组末尾运行或在删除后取消引用指针)或程序中某个较早时间点的其他未定义行为而发生。

您的程序一次尝试使用多少内存?您可以尝试使用像valgrind 这样的检漏仪来查看是否有需要清理的东西。

编辑

-1 to __builtin_new 告诉您很多信息——它告诉您有人用伪造的尺寸打电话给 new。那可能是试图调整大小的 std::vector 的成员(您可以检查来自 valgrind 的堆栈跟踪或使用调试器来确定),这表明向量已损坏。由于sample.second 是一个本地(在堆栈上)变量,它告诉您之前调用的函数(可能是getDetections)超出了某种类型的堆栈缓冲区或数组并破坏了sample.second。所以仔细看看那个函数在做什么——你注释掉的代码是//some processing。您还可以尝试在创建sample 之后使用调试器设置断点,然后在sample.second 使用的内存上设置一个观察点,该内存已损坏。然后继续该程序,它应该会停止在破坏sample.second

阅读编译器的头文件以了解它如何实现 std::vector 可能会有所帮助——其中可能有几个 size_t 字段和一个指针字段。

【讨论】:

  • 好吧,感谢您的建议,但我首先尝试的是 valgrind。它只打印silly arg (-1) to __builtin_new() 并且堆栈跟踪导致上面的标记行
  • 这是一个线索。运算符 new 需要 size_t。在 32 位机器上,(size_t)-1 是 4 GB。这解释了 std::bad_alloc 异常。
  • 好吧,@Chris 如果没有//some processing,它肯定会以同样的方式失败。但我检查了一件有趣的事情:调试器告诉我 sample.second 仍然是 0 元素,尽管我将第一个推回没有错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-16
  • 1970-01-01
  • 1970-01-01
  • 2013-08-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多