traceback a pointer in c++ code gdb

前端 未结 2 1974
谎友^
谎友^ 2020-12-02 01:21

I am getting seg fault while running a c++ application. In gdb it shows somehow my one pointer location getting corrupted. But I have 100 thousands of such object pointers c

相关标签:
2条回答
  • 2020-12-02 01:39

    I had some mem-leaks problems in the past (caused by compiler bug) in apps with about 256K pointers so i had to check it somehow. After some struggle I created a table of all allocated pointers and their sizes and some functions to keep it updated. the result is this:

    File: mmap.h

    //---------------------------------------------------------------------------
    //--- Memory map system ver: 2.03 -------------------------------------------
    //---------------------------------------------------------------------------
    #ifndef _mmap_h
    #define _mmap_h
    //---------------------------------------------------------------------------
    #define _mmap_aprox
    //---------------------------------------------------------------------------
    /*
        new
        #ifdef _mmap_h
        if () mmap_new('Main',,sizeof());
        #endif
    
        #ifdef _mmap_h
        if () mmap_del('Main',);
        #endif
        delete
    */
    //---------------------------------------------------------------------------
    struct _mmap_entry
        {
        char ids[4];                            // id string
        DWORD beg,end;                          // mem adr <beg,end)
        _mmap_entry(){ beg=0; end=0; ((DWORD*)(ids))[0]='LLUN'; };
        _mmap_entry(_mmap_entry& a) { *this=a; }
        ~_mmap_entry()  {}
        _mmap_entry* operator = (const _mmap_entry *a) { *this=*a; return this; }
        //_mmap_entry* operator = (const _mmap_entry &a) { ...copy... return this; }
        };
    //---------------------------------------------------------------------------
    const int _mmap_entries=4*1024;             // max num of allocated memory chunks (pointers)
    const int _mmapn_entries=32;                // num of last news to remember
    const int _mmapd_entries=32;                // num of last dels to remember
    static _mmap_entry mmap [_mmap_entries];    // memory map table active ptrs
    static _mmap_entry mmapn[_mmapn_entries];   // memory map table last news
    static _mmap_entry mmapd[_mmapd_entries];   // memory map table last dels
    static int mmaps=0;                         // num of used entries in memory map table
    static int mmapn_ix=0;                      // num of last deletes to remember
    static int mmapd_ix=0;                      // num of last deletes to remember
    static int mmap_errs=0;                     // error count
    static int mmap_news=0;                     // allocations count
    static int mmap_dels=0;                     // deallocations count
    //---------------------------------------------------------------------------
    void mmap_err(const char* msg,DWORD ptr)    // breakpointeable error
        {
        mmap_errs++;
        }
    //---------------------------------------------------------------------------
    int mmap_new(DWORD ids,void* ptr,DWORD siz) // tracks all allocations return false if error
        {
        mmap_news++;
        int i,j; _mmap_entry e,*p;
        e.beg=DWORD(ptr);
        e.end=e.beg+siz;
        e.ids[0]=((char*)&ids)[3];
        e.ids[1]=((char*)&ids)[2];
        e.ids[2]=((char*)&ids)[1];
        e.ids[3]=((char*)&ids)[0];
        if (e.beg==0)
            {
            mmap_err("Not enough memory.",e.beg);
            return 0;
            }
        // find first i where mmap[i].end >= e.beg
        #ifdef _mmap_aprox
        if (!mmaps) i=0;
        else{
            for (j=1;j<mmaps;j<<=1); j>>=1; if (!j) j=1;
            for (i=0;j;j>>=1)
                {
                i|=j;
                p=mmap+i;
                if ((i>=mmaps)||(e.beg<p->end)) i^=j;
                if ((e.beg<p->end)&&(e.end>p->beg))
                    {
                    mmap_err("Bad allocation.",e.beg);      // memory already allocated
                    return 0;
                    }
                }
            if (e.beg>=mmap[i].end) i++;
            }
        #endif
        #ifndef _mmap_aprox
        for (i=mmaps-1,p=mmap+i;i>=0;i--,p--)
         if (e.beg<p->end)
            {
            if (e.end>p->beg)
                {
                mmap_err("Bad allocation.",e.beg);      // memory already allocated
                return 0;
                }
            } else break; i++;
        #endif
        // insert new pointer at i
        if (mmaps>=_mmap_entries)
            {
            mmap_err("Too many pointers.",e.beg);   // _mmap_entries is too low
            return 0;
            }
        for (j=mmaps;j>i;j--) mmap[j]=mmap[j-1];
        mmap[i]=e; mmaps++;
        // remember last new in mmapn table
        mmapn[mmapn_ix]=e; mmapn_ix++;
        if (mmapn_ix>=_mmapn_entries) mmapn_ix=0;
        return 1;
        };
    //---------------------------------------------------------------------------
    int  mmap_del(DWORD ids,void* ptr)              // tracks all deallocations return false if error
        {
        mmap_dels++;
        int i,j; _mmap_entry *p;
        DWORD adr=DWORD(ptr);
        if (adr==0)
            {
            mmap_err("Can not delete NULL.",adr);
            return 0;
            }
        if (mmap<=0)
            {
            mmap_err("Nothing to delete.",adr);
            return 0;
            }
        // find mmap[i] where beg==ptr and delete it if found
        #ifdef _mmap_aprox
        if (!mmaps) i=0;
        else{
            for (j=1;j<mmaps;j<<=1); j>>=1; if (!j) j=1;
            for (i=0;j;j>>=1)
                {
                i|=j;
                p=mmap+i;
                if ((i>=mmaps)||(adr<p->beg)) i^=j;
                }
            if (adr==mmap[i].beg)
                {
                if (mmaps>1) for (j=i;j<mmaps-1;j++) mmap[j]=mmap[j+1];
                mmaps--;
                // remember last delete in mmapd table
                mmapd[mmapd_ix]=mmap[mmaps]; mmapd_ix++;
                if (mmapd_ix>=_mmapd_entries) mmapd_ix=0;
                // delete ptr from mmap table
                mmap[mmaps].beg=0;
                mmap[mmaps].end=0;
                return 1;
                }
            for (p=mmap,j=0;j<=i;j++,p++)               // test all mmap[j].beg < adr
             if (adr<p->end)                            // if overlap then ...
                {
                mmap_err("Wrong delete pointer.",adr);  // pointer inside already allocated space
                return 0;
                }
            }
        #endif
        #ifndef _mmap_aprox
        for (p=mmap,i=0;i<mmaps;i++,p++)
         if (p->beg==adr)
            {
            if (mmaps>1) for (j=i;j<mmaps-1;j++) mmap[j]=mmap[j+1];
            mmaps--;
            mmap[mmaps].beg=0;
            mmap[mmaps].end=0;
            return 1;
            } else if (p->beg>adr) break;
        for (p=mmap,i=0;i<mmaps;i++,p++)
         if ((adr>p->beg)&&(adr<p->end))
            {
            mmap_err("Wrong delete pointer.",adr);  // pointer inside already allocated space
            return 0;
            }
        #endif
        mmap_err("Delete pointer not found.",adr);
        return 0;
        };
    //---------------------------------------------------------------------------
    #endif
    //---------------------------------------------------------------------------
    //---------------------------------------------------------------------------
    

    Now in your code just do this:

    // edit the safe big enough number of pointers to use for your application in begin of the mmap.h
    _mmap_entries=512*1024;
    
    // before any delete/delete[] of pointer ptr add this:
    #ifdef _mmap_h
    if (ptr!=NULL) mmap_del('info',ptr);
    #endif
    if (ptr!=NULL) delete[] ptr;
    
    // after any new of pointer ptr of size siz [byte] add this:
    ptr=new BYTE[siz];
    #ifdef _mmap_h
    if (ptr!=NULL) mmap_new('info',ptr,siz);
    #endif
    

    So if you include mmap.h as a first include !!!

    • place breakpoint inside function void mmap_err(const char* msg,DWORD ptr)
    • run application
    • if any allocation error occurs then it will break before exception so you can actually see the info and kind off error and also can step to code where error occurs

    I am BDS2006 Turbo C++ user so if I forgot some VCL stuff just convert it to MSVC++ or comment me and i will do it, but I don't see anything what could cause troubles.

    PS. I found out that for my compiler is a fatal error to:

    1. delete pointer more than once
    2. have structs without proper constructor/destructors

    in both cases no exception is thrown but memory manager is corrupted afterwards so it allocates wrongly hence exceptions

    Proper constructors/destructors for my compiler
    for all structs and classes which will be dynamically allocated or any of their component
    is like this:

    class/struct T
        {
    public:
        T()     {}
        T(T& a) { *this=a; }
        ~T()    {}
        T* operator = (const T *a) { *this=*a; return this; }
    
        // if any dynamic allocation occur then this must be done also else not
        //T* operator = (const T &a) { ... copy a to this ... return this; }
        };
    
    0 讨论(0)
  • 2020-12-02 01:57

    As far as I know you can't get such information with help of gdb, but for these purpose you can try valgrind memcheck with option --track-origins

    0 讨论(0)
提交回复
热议问题