使用Valgrind调试程序-检测分段故障

Debugging a program using Valgrind - Detecting a segmentation fault

本文关键字:分段 故障 检测 Valgrind 调试程序 使用      更新时间:2023-10-16

我有一个类a和一个从a:派生的类B

class A
{
  public :
  A() { // Some code }
  virtual ~A(){}
  // etc
};

这是我的B级:

class B : public A
{
  public :
  B():A(){//Some extra code}
  ~B();
  // etc
};

A和B的实际代码很长,所以我不会把它贴在那里,除非有必要。

我的问题是,在我的主程序中:

  • 当我实例化A时,它没有问题
  • 当我实例化B时,我可以"玩"它(访问其成员等),但当程序完成时,我出现了segfault

只有当我有一个B的实例时,segfault才会出现。

所以,为了找到我的问题所在,我试图使用Valgrind,但我很困,因为我不明白Valgrind在显示什么。

Valgrind的输出相当长,但其中有一个方案,结果如下:

==13512== Invalid read of size 4
==13512==    at 0x852EE9D: __tcf_0 (in /usr/local/lib/libeikeotools.so)
==13512==    by 0x6AE15E9: __cxa_finalize (cxa_finalize.c:56)
==13512==    by 0x84C3E72: ??? (in /usr/local/lib/libeikeotools.so)
==13512==    by 0x4010739: _dl_fini (dl-fini.c:252)
==13512==    by 0x6AE1258: __run_exit_handlers (exit.c:82)
==13512==    by 0x6AE12A4: exit (exit.c:104)
==13512==    by 0x6AC6ECB: (below main) (libc-start.c:321)
==13512==  Address 0x131e4d00 is 16 bytes inside a block of size 32 free'd
==13512==    at 0x4C2C2BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13512==    by 0x664536E: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==13512==    by 0x73A3384: __tcf_0 (logwriter.cpp:32)
==13512==    by 0x6AE15E9: __cxa_finalize (cxa_finalize.c:56)
==13512==    by 0x7301A72: ??? (in /usr/local/lib/libeikeotoolsd.so)
==13512==    by 0x4010739: _dl_fini (dl-fini.c:252)
==13512==    by 0x6AE1258: __run_exit_handlers (exit.c:82)
==13512==    by 0x6AE12A4: exit (exit.c:104)
==13512==    by 0x6AC6ECB: (below main) (libc-start.c:321)
==13512== 
==13512== Invalid free() / delete / delete[] / realloc()
==13512==    at 0x4C2C2BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13512==    by 0x852EEB3: __tcf_0 (in /usr/local/lib/libeikeotools.so)
==13512==    by 0x6AE15E9: __cxa_finalize (cxa_finalize.c:56)
==13512==    by 0x84C3E72: ??? (in /usr/local/lib/libeikeotools.so)
==13512==    by 0x4010739: _dl_fini (dl-fini.c:252)
==13512==    by 0x6AE1258: __run_exit_handlers (exit.c:82)
==13512==    by 0x6AE12A4: exit (exit.c:104)
==13512==    by 0x6AC6ECB: (below main) (libc-start.c:321)
==13512==  Address 0x131e4cf0 is 0 bytes inside a block of size 32 free'd
==13512==    at 0x4C2C2BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13512==    by 0x664536E: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==13512==    by 0x73A3384: __tcf_0 (logwriter.cpp:32)
==13512==    by 0x6AE15E9: __cxa_finalize (cxa_finalize.c:56)
==13512==    by 0x7301A72: ??? (in /usr/local/lib/libeikeotoolsd.so)
==13512==    by 0x4010739: _dl_fini (dl-fini.c:252)
==13512==    by 0x6AE1258: __run_exit_handlers (exit.c:82)
==13512==    by 0x6AE12A4: exit (exit.c:104)
==13512==    by 0x6AC6ECB: (below main) (libc-start.c:321)

第1版:这是我的"B"级:

HOGpython.hp:

#ifndef HOGPYTHON_H
#define HOGPYTHON_H
#include "osell/cvaddenda/HOGDescriptor2.h"
#include <opencv2/core/core.hpp>
#include "conversion.hpp"
#define NO_IMPORT_ARRAY
class  HOGpython : public eikeotools::CvAddenda::HOGDescriptor2
{
    public:
        // Constructeurs :
        HOGpython();
        HOGpython(PyObject* _winSize, PyObject* _blockSize, PyObject* _blockStride, PyObject* _cellSize, int _nbins, double _winSigma);
        // Destructeur :
        ~HOGpython(){ std::cout << " Destroying .." << std::endl;}
        // setters :
        PyObject*   get_winSize() const;
        PyObject*   get_blockSize() const;
        PyObject*   get_blockStride() const;
        PyObject*   get_cellSize() const;
        int         get_nbins() const;
        int         get_derivAperture() const;
        double      get_winSigma() const;
        int         get_histogramNormType() const;
        double      get_L2HysThreshold() const;
        bool        get_gammaCorrection() const;
        int         get_nlevels() const;
        // Setters :
        void    set_winSize( PyObject* o);
        void    set_blockSize( PyObject* o);
        void    set_blockStride( PyObject* o);
        void    set_cellSize( PyObject* o);
        void    set_nbins( int o);
        void    set_derivAperture( int o);
        void    set_winSigma( double o);
        void    set_histogramNormType( int o);
        void    set_L2HysThreshold( double o);
        void    set_gammaCorrection( bool o);
        void    set_nlevels( int o);
        // Méthodes d'instance :
        PyObject* compute(PyObject* img, PyObject* locations);
        PyObject* computeSubPix(PyObject* img, PyObject* locations);
        PyObject* computeGradient(PyObject* img);
};
#endif

和HOGpython.cpp:

#include "HOGpython.hpp"


// ==  Constructeur sans paramètres == //
HOGpython :: HOGpython():eikeotools::CvAddenda::HOGDescriptor2()
{}
// ==  Constructeur avec paramètres == //
HOGpython :: HOGpython(PyObject* _winSize, PyObject* _blockSize, PyObject* _blockStride, PyObject* _cellSize, int _nbins, double _winSigma)
    :eikeotools::CvAddenda::HOGDescriptor2( tupleToSize(_winSize),
                                            tupleToSize(_blockSize),
                                            tupleToSize(_blockStride),
                                            tupleToSize(_cellSize),
                                            _nbins,
                                            1,
                                            _winSigma,
                                            eikeotools::CvAddenda::HOGDescriptor2::L2Hys,
                                            0.2,
                                            false,
                                            eikeotools::CvAddenda::HOGDescriptor2::DEFAULT_NLEVELS)
{}
// ==  Getters == //
PyObject*   HOGpython::get_winSize()            const   {return SizeToTuple(winSize);       }
PyObject*   HOGpython::get_blockSize()          const   {return SizeToTuple(blockSize);     }
PyObject*   HOGpython::get_blockStride()        const   {return SizeToTuple(blockStride);   }
PyObject*   HOGpython::get_cellSize()           const   {return SizeToTuple(cellSize);      }
int         HOGpython::get_nbins()              const   {return nbins;                      }
int         HOGpython::get_derivAperture()      const   {return derivAperture;              }
double      HOGpython::get_winSigma()           const   {return winSigma;                   }
int         HOGpython::get_histogramNormType()  const   {return histogramNormType;          }
double      HOGpython::get_L2HysThreshold()     const   {return L2HysThreshold;             }
bool        HOGpython::get_gammaCorrection()    const   {return gammaCorrection;            }
int         HOGpython::get_nlevels()            const   {return nlevels;                    }
// ==  Setters == //
void    HOGpython::set_winSize(PyObject* o)     {winSize            = tupleToSize(o);}
void    HOGpython::set_blockSize(PyObject* o)   {blockSize          = tupleToSize(o);}
void    HOGpython::set_blockStride(PyObject* o) {blockStride        = tupleToSize(o);}
void    HOGpython::set_cellSize(PyObject* o)    {cellSize           = tupleToSize(o);}
void    HOGpython::set_nbins(int o)             {nbins              = o; return;}
void    HOGpython::set_derivAperture(int o)     {derivAperture      = o; return;}
void    HOGpython::set_winSigma(double o)       {winSigma           = o; return;}
void    HOGpython::set_histogramNormType(int o) {histogramNormType  = o; return;}
void    HOGpython::set_L2HysThreshold(double o) {L2HysThreshold     = o; return;}
void    HOGpython::set_gammaCorrection(bool o)  {gammaCorrection    = o; return;}
void    HOGpython::set_nlevels(int o)           {nlevels            = o; return;}

PyObject* HOGpython::compute(PyObject* img, PyObject* locations)
{
    //  Déclaration d'instances :
    cv::Mat im, pt;
    PyObject* ret;
    // Conversion :
    NDArrayConverter cvt;
    im = cvt.toMat(img);
    pt = cvt.toMat(locations);
    // Déclaration de vecteurs :
    std::vector<float> desc;
    std::vector<cv::Point> pts;
    //Py_BEGIN_ALLOW_THREADS;
    PyThreadState * m_thread_state;
    m_thread_state = PyEval_SaveThread();
    for(int i = 0; i < pt.rows; i++)
    {
        pts.push_back(cv::Point(pt.at<double>(i,0), pt.at<double>(i,1)));
    }
    eikeotools::CvAddenda::HOGDescriptor2::compute(im,desc,cv::Size(),cv::Size(),pts, false);
    PyEval_RestoreThread(m_thread_state);
    m_thread_state = NULL;
    //Py_END_ALLOW_THREADS;
    cv::Mat pointsMat = cv::Mat(desc);
    ret = cvt.toNDArray(pointsMat);
    return ret;
}

PyObject* HOGpython::computeSubPix(PyObject* img, PyObject* locations)
{
    //  Déclaration d'instances :
    cv::Mat im, pt;
    PyObject* ret;
    // Conversion :
    NDArrayConverter cvt;
    im = cvt.toMat(img);
    pt = cvt.toMat(locations);
    // Déclaration de vecteurs :
    std::vector<float> desc;
    std::vector<cv::Point2f> pts;
    //Py_BEGIN_ALLOW_THREADS;
    PyThreadState * m_thread_state;
    m_thread_state = PyEval_SaveThread();
    for(int i = 0; i < pt.rows; i++)
    {
        pts.push_back(cv::Point(pt.at<double>(i,0), pt.at<double>(i,1)));
    }
    eikeotools::CvAddenda::HOGDescriptor2::computeSubPix(im,desc,cv::Size(),cv::Size(),pts, false);
    PyEval_RestoreThread(m_thread_state);
    m_thread_state = NULL;
    //Py_END_ALLOW_THREADS;
    cv::Mat pointsMat = cv::Mat(desc);
    ret = cvt.toNDArray(pointsMat);
    return ret;
}
PyObject* HOGpython::computeGradient(PyObject* img)
{
    // Déclaration d'instances :
    cv::Mat im, grad, angleOfs;
    PyObject* listeRes;
    PyObject* grad_;
    PyObject* angleOfs_;
    // Conversion :
    NDArrayConverter cvt;
    im = cvt.toMat(img);
    //Py_BEGIN_ALLOW_THREADS;
    PyThreadState * m_thread_state;
    m_thread_state = PyEval_SaveThread();
    eikeotools::CvAddenda::HOGDescriptor2::computeGradient(im, grad, angleOfs, cv::Size(), cv::Size());
    PyEval_RestoreThread(m_thread_state);
    m_thread_state = NULL;
    //Py_END_ALLOW_THREADS;
    // Conversion :
    grad_ = cvt.toNDArray(grad);
    angleOfs_ = cvt.toNDArray(angleOfs);
    // Création d'une liste Python dans laquelle les deux résultats seront enregistrés :
    listeRes = PyList_New(0);
    PyList_Append(listeRes, grad_);
    PyList_Append(listeRes, angleOfs_);
    // Renvoie des données :
    return listeRes;
    }

不幸的是,我不能显示我的类A(框架的一部分),但我可以看出A不会导致任何分段错误。

为了总结我的代码,我想为python制作一个类a的包装器,因为a包含一些OpenCV对象,Boost。Python无法自动转换它们,所以我创建了从A派生的B,但从opencv对象到Python对象进行了一些转换。

为了进行转换,我有一个运行良好的转换模块。我想补充一点:这是我的主要代码,给了我一个segfault:

int main()
{
  HOGpython h;
  return 0;
}

这看起来像是调用了全局对象的析构函数(可能是std::string或与std::string有某种关系的东西),但要么该对象被手动删除,要么有人获得了该对象的所有权并将其删除。

请与我们分享更多的代码,logwriter类的源代码不应该包含非常敏感的数据,它的存在可能有助于实际识别错误。

顺便说一句,请确保~B();实际上有一个实现。

好的,我解决了这个问题。。这与我的代码无关。

这个问题来自于冲突的共享库,我想我使用的框架安装得不好。我把它拆了,完全重新安装,一切都很好。

问题解决了!