push_back中的分段错误()

时间:2014-11-27 10:48:05

标签: c++ stl

我在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
  }
}

来自评论的错误消息

 #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  

1 个答案:

答案 0 :(得分:1)

发布的代码看起来很危险

  • 原始指针
  • 没有析构函数/复制构造函数/赋值运算符(规则3(C ++ 03),规则5(C ++ 11)
  • 没有明确的数据所有权。
  • 删除后可能会使用数据。
  • 缺少检查clLoadImage是否失败。

见评论:

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,则调用默认析构函数,删除其向量中的所有B。在所示的程序部分中没有一个是错误的。

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再次删除该图像,从而破坏堆。