回溯 C++ 代码 gdb 中的指针

Posted

技术标签:

【中文标题】回溯 C++ 代码 gdb 中的指针【英文标题】:traceback a pointer in c++ code gdb 【发布时间】:2014-01-01 03:04:34 【问题描述】:

我在运行 C++ 应用程序时遇到 seg 错误。在 gdb 中,它以某种方式显示我的一个指针位置已损坏。但是我在我的应用程序中创建了 10 万个这样的对象指针。我怎样才能看到导致崩溃的一个 我可以在 bt 命令中执行任何操作来查看该指针的生命周期吗?

谢谢 汝驰

【问题讨论】:

看看 valgrind,它应该会给你你需要的信息 【参考方案1】:

据我所知,在 gdb 的帮助下您无法获得此类信息,但出于这些目的,您可以尝试使用选项 --track-origins 的 valgrind memcheck

【讨论】:

谢谢 sim,能否请您告诉我 trace-origins 的语法。我无法获得 valgrind 帮助? 4. Memcheck: a memory error detector4.3. Memcheck Command-Line Options【参考方案2】:

我过去在具有大约 256K 指针的应用程序中遇到了一些内存泄漏问题(由编译器错误引起),因此我不得不以某种方式对其进行检查。经过一番努力,我创建了一个包含所有已分配指针及其大小的表以及一些保持更新的函数。结果是这样的:

文件: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
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------

现在在您的代码中执行以下操作:

// 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

所以如果你包含 mmap.h 作为第一个包含!!!

在函数 void mmap_err(const char* msg,DWORD ptr) 中放置断点 运行应用程序 如果发生任何分配错误,那么它将在异常之前中断,因此您可以实际查看信息和类型错误,并且还可以在发生错误的位置进行代码处理

我是 BDS2006 Turbo C++ 用户,所以如果我忘记了一些 VCL 内容,只需将其转换为 MSVC++ 或评论我,我会这样做,但我没有看到任何可能导致麻烦的东西。

附言。我发现对于我的编译器来说是一个致命错误:

    多次删除指针 具有没有适当构造函数/析构函数的结构

在这两种情况下都没有抛出异常,但内存管理器随后被损坏,因此分配错误,因此出现异常

适合我的编译器的构造函数/析构函数 对于将动态分配的所有结构和类或其任何组件 是这样的:

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; 
    ;

【讨论】:

以上是关于回溯 C++ 代码 gdb 中的指针的主要内容,如果未能解决你的问题,请参考以下文章

使用 gdb 检查指针是不是可能在核心转储中有效 [重复]

在向量 C++ 中处理指针

如何在 C++ 中跟踪无效指针?

多线程程序中的分段错误和 gdb 回溯信息不完整

修复 C++ 中的分段错误

DEV C++ 中的 GDB 在 cout 上停止