【问题标题】:Segmentation Fault in push_back()push_back() 中的分段错误
【发布时间】:2014-11-27 10:48:04
【问题描述】:

我在 push_back() 中遇到分段错误,我在下面给出了我的项目的示例代码。我没有在 vec 中使用 image(IplImage*),因为我在 push_back() 之后清除了 temp (IplImage*)

我的疑问是这个,我应该更换...

a.cands.push_back(b);

...与...

 b.frontImg = NULL;
 a.cands.push_back(b);

...?

程序:

#include<iostream>
#include<vector>
#include<highgui.h>
#include<cv.h>

using namespace std;

struct B
{
  IplImage* frontImg;
  vector<int> num;
  B()
  {
    frontImg = NULL;
  }
}; 

struct A
{
  vector<B> cands;
  IplImage* img1;
  A()
  {
    img1 = NULL;
  }
};

vector<A> vec;

int main()
{
  for (int i = 0; i < 1000; i++)
  {
    struct B b;
    IplImage* temp = cvLoadImage("logo.jpg");
    b.frontImg = temp;

    struct A a;

    for (int j = 0; j<1000; j++)
    {
      a.cands.push_back(b);
    }

    vec.push_back(a); //here

    cvReleaseImage(&temp);

    //some porcess
  }
}

来自 cmets 的错误消息

 #0 0x000000353a0328a5 in raise () from /lib64/libc.so.6  
 #1 0x000000353a034085 in abort () from /lib64/libc.so.6  
 #2 0x000000353a0707b7 in __libc_message () from /lib64/libc.so.6  
 #3 0x000000353a0760e6 in malloc_printerr () from /lib64/libc.so.6  
 #4 0x000000353a079b64 in _int_malloc () from /lib64/libc.so.6  
 #5 0x000000353a07a911 in malloc () from /lib64/libc.so.6  
 #6 0x0000000000688a7d in operator new(unsigned long)  
 #7 ???  
 #8 0x0000000000563fdd in std::_Vector_base<CvPoint, std::allocator<CvPoint> >::_M_allocate (this=0x7f31ad14bb90, __n= 1096) at /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/bits/stl_ve‌​ctor.h:140  
 #9 0x0000000000560491 in std::_Vector_base<CvPoint, std::allocator<CvPoint> >::_Vector_base (this=0x7f31ad14bb90, __n= 1096, __a=...) at /usr/lib/gcux/4.4.7./include/c++/4.4.7/bits/stl_vector.h:113  
 #10 0055ebc1 in std::vector<CvPoint, std::allocator<CvPoint> >::vector (this=0x7f31ad14bb90, __x= std::vector of length 1096, capacity 1096 = {../include/c++/  
 #11 ???  
 #12 ???  
 #13 ???  
 #14 0x000000000055f346 in std::vector<LPCandidate, std::allocator<LPCandidate> >::push_back (this=0x7f31ac00ddb0, __x= ...) at /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/bits/stl_ve‌​ctor.h:737  
 #15 0x0000000000556689 in KLPR::TrManager::segregateLane (this=0x7f31ac0008e8, candLPV= std::vector of length 6, capacity 32 = {...}, candIndex=0x7f31b3ffd500) at MyProject/src/TrManager.cpp:2026  

【问题讨论】:

  • 您发布的代码没有任何问题 - 在 ideone here 上使用模拟 cvXXX 函数和类型运行良好 - cvReleaseImage() 没有释放您所有的内存或您的“某些进程”[ sic] 具有未定义的行为(例如破坏堆)并且在push_back() 期间巧合地咬了。我不明白你为什么要加载图像然后释放它而不用它做任何事情,所以我认为你没有让我们对你的问题有一个现实的看法。
  • 上面给出的代码没有崩溃,但这是我在我的项目中所做的..很难给出实际代码..所以我创建了一个与我的项目类似的代码
  • @deepak:这不是分段错误,而是堆管理器中止,因为您损坏了堆(通过写入无效指针或超出分配的内存块的范围)。我会使用 Valgrind 来查找无效的写入。
  • @Mike Seymour 你能解释一下吗?
  • @deepak:某些代码(可能不是您发布的内容)通过指向已删除对象的指针(或其他一些无效指针)写入,或者超出分配的内存块的末尾,或类似的规定。这会破坏malloc 用来管理用于动态分配内存的堆的数据结构。稍后对malloc 的调用(当向量在push_back 期间增加其容量时间接发生)注意到此损坏并中止程序,因为它处于无法分配内存的状态。像Valgrind 这样的工具可以提供帮助。

标签: c++ stl


【解决方案1】:

发布的代码看起来很危险

  • 原始指针
  • 无析构函数/复制构造函数/赋值运算符(规则 3 (C++03)、规则 5 (C++11)
  • 没有明确的数据所有权。
  • 删除后数据的潜在用途。
  • 如果 clLoadImage 失败,则缺少检查。

见 cmets:

struct B b;
IplImage* temp = cvLoadImage("logo.jpg");
b.frontImg = temp;

struct A a;

for (int j = 0; j<1000; j++)
  a.cands.push_back(b);

现在您有 1000 个元素指向 cvLoadImage 返回的图像,我假设您在实际程序中为每个 b.frontImg 加载不同的图像。

vec.push_back(a); //here

A 的默认复制构造函数被调用,如果a 不再使用as 默认析构函数被调用,这将删除其向量中的所有Bs。显示的程序部分都没有错误。

cvReleaseImage(&temp);

现在您也释放这 1000 个元素所指向的内容(如果是 cvLoadImage,如果以后不使用 b.frontImg 也不是问题。

//some process

这里希望不要通过B中的指针使用刚刚发布的图片。


现在回答你的问题,是的,你应该使用

b.frontImg = NULL;
a.cands.push_back(b);

因为它消除了很多问题,因为现在没有人可以通过b复制或删除图像(如果你记得之后删除图像)。


原始指针如何危险的一个例子,添加

~B() { delete frontImg; } // or some user of B decides to delete frontImg itself.

到代码,但没有复制构造函数或复制赋值运算符。现在每次你做一个

a.cands.push_back(b);  // implicit copy construct of a new b.

b 稍后在超出范围时被销毁。您有效地推回了指向已删除图像的b,当您删除a 时,您再次通过向量的b 删除图像,从而破坏了堆。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多