Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何修复C++;_C++_Macos_Debug Symbols_Backtrace - Fatal编程技术网

C++ 如何修复C++;

C++ 如何修复C++;,c++,macos,debug-symbols,backtrace,C++,Macos,Debug Symbols,Backtrace,我想跟踪一些程序捕获异常的信息时遇到问题 我使用了以下功能: extern "C" void log_backtrace() { // Dump the callstack int callstack[128]; int frames = backtrace((void**) callstack, 128); char** strs = backtrace_symbols((void**) callstack, frames); for (int

我想跟踪一些程序捕获异常的信息时遇到问题

我使用了以下功能:

extern "C" void log_backtrace()
{   
    // Dump the callstack
    int callstack[128];
    int  frames = backtrace((void**) callstack, 128);
    char** strs = backtrace_symbols((void**) callstack, frames);

    for (int i = 1; i < frames; ++i)
    {
        char functionSymbol[64*1024];
        char moduleName    [64*1024];
        int  offset        = 0;
        sscanf(strs[i], "%*d %s %*s %s %*s %d", &moduleName, &functionSymbol, &offset);
        int addr = callstack[i];
        int   validCppName;
        char* functionName = abi::__cxa_demangle(functionSymbol, NULL, 0,
                                             &validCppName);
        if (validCppName == 0)
            printf(   "\t%8.8x — %s + %d\t\t(%s)\n", addr, functionName, offset, moduleName);
        else
            printf(   "\t%8.8x — %s + %d\t\t(%s)\n", addr, functionSymbol, offset, moduleName);
        if (functionName)
            free(functionName);
    }
    free(strs);
}
extern“C”void log\u backtrace()
{   
//转储调用堆栈
int调用堆栈[128];
int frames=backtrace((void**)调用堆栈,128);
char**strs=backtrace_符号((void**)调用堆栈,帧);
对于(int i=1;i
输出如下:

20:48:44 [ERROR]tcp_client::connect() failed. error:Connection refused
00000001 — latte::Log::out_error(std::string const&) + 151      (valhalla)
001a6637 — latte::tcp_client::connect(boost::asio::ip::basic_endpoint<boost::asio::ip::tcp> const&) + 307       (valhalla)
00000001 — valhalla::hall::start() + 388        (valhalla)
00204803 — main + 388       (valhalla)
00000001 — start + 52       (valhalla)
00143ae4 — 0x0 + 1      (???)
20:48:44[错误]tcp_客户端::connect()失败。错误:连接被拒绝
00000001-latte::Log::out_错误(std::string const&)+151(valhalla)
001a6637-拿铁::tcp_客户端::连接(boost::asio::ip::基本_端点常数&)+307(valhalla)
00000001-valhalla::hall::start()+388(valhalla)
00204803-干管+388(瓦尔哈拉)
00000001-启动+52(瓦尔哈拉)
00143ae4-0x0+1(?)
所有信息(名称空间、类名和方法名)都很好。但唯一的问题是行号错了


如何修复回溯中的行号?

它们不是行号,而是从函数开始的偏移量。有一个名为
addr2line
的工具,它与binutils一起提供,可以将地址转换为给定调试符号的行号。您可以从程序中调用它(
pipe()
+
fork()
+
exec()
),也可以查看它用于执行此操作的库


在我的Linux系统上,addr2line在内部用于此目的。虽然从我所看到的来看,它并没有很好的文档记录,但是从addr2line源代码中通过示例可以很容易地看到它。

我也遇到过同样的问题,并四处寻找解决方案,但我什么也没找到。你已经在你的帖子中标记了OSX,所以我假设这就是你想让它工作的平台?OSX没有addr2line,至少OSX版本10.8/10.9中没有。我将下面的代码放在一起(使用来自不同来源的代码片段),它生成如下所示的回溯(它包括最上面的两个帧,它们是异常处理程序,如果您愿意,可以跳过这两个帧):

它只为执行模块中的帧生成函数+文件+行号。该代码仅适用于OSX,但也可适用于其他平台。将会有一些角落案例没有被涵盖,但希望这是一个好的起点。代码是:

namespace ExceptionHandler
{
    char m_ExeFilename[ PATH_MAX ];

    // Execute cmd store stdout into buf (up to bufSize).
    int Execute( const char * cmd, char * buf, size_t bufSize )
    {
        char filename[ 512 ];
        sprintf( filename, "%d.tmp", rand( ) );

        if ( FILE * file = fopen( filename, "w" ) )
        {
            if ( FILE * ptr = popen( cmd, "r" ) ) 
            {
                while ( fgets( buf, bufSize, ptr ) != NULL )
                {
                    fprintf( file, "%s", buf );
                }
                pclose( ptr );
            }
            fclose( file );

            unlink( filename );

            return 0;   
        }

        return -1;
    }

    // Resolve symbol name and source location given the path to the executable and an address
    int Addr2Line(char const * const program_name, void const * const addr, char * buff, size_t buffSize )
    {
        char addr2line_cmd[512] = {0};
        sprintf( addr2line_cmd, "atos -d -o %.256s %p", program_name, addr ); 
        return Execute( addr2line_cmd, buff, buffSize );
    }

    // Check if file exists.
    bool FileExists( const char * filename )
    {
        if ( FILE * fh = fopen( filename, "r" ) )
        {
            fclose( fh );
            return true;
        }

        return false;
    }

    // Print stack trace.
    void PrintStackTrace( )
    {
        int trace_size = 0;
        char ** messages = ( char ** )NULL;

        static const size_t kMaxStackFrames = 64;
        static void * stack_traces[ kMaxStackFrames ];
        trace_size = backtrace( stack_traces, kMaxStackFrames );
        messages = backtrace_symbols( stack_traces, trace_size );

        for ( int i = 0; i < trace_size; ++i )
        {
            int stackLevel;
            char filename[ 512 ];
            uintptr_t address;
            char symbol[ 512 ];
            uintptr_t symbolOffset;
            uintptr_t functionOffset;
            bool symbolOffsetValid = false;
            bool somethingValid = true;

            if ( sscanf( messages[ i ], "%d%*[ \t]%s%*[ \t]%" SCNxPTR "%*[ \t]%" SCNxPTR "%*[ \t]+%*[ \t]%" SCNuPTR, &stackLevel, filename, &address, &symbolOffset, &functionOffset ) == 5 )
            {
                symbolOffsetValid = true;
            }
            else if ( sscanf( messages[ i ], "%d%*[ \t]%s%*[ \t]%" SCNxPTR "%*[ \t]%s%*[ \t]+%*[ \t]%" SCNuPTR, &stackLevel, filename, &address, symbol, &functionOffset ) == 5 )
            {
            }
            else
            {
                somethingValid = false;
            }

            const size_t BUFF_SIZE = 4096;
            char buff[ BUFF_SIZE ] = { '\0' };

            if ( somethingValid )
            {
                if ( symbolOffsetValid && symbolOffset == 0 )
                {
                    fprintf( stderr, "%3d %-32s   %#16" PRIxPTR "   %#" PRIxPTR " + %" PRIuPTR "\n", stackLevel, filename, address, symbolOffset, functionOffset );
                }
                else if ( FileExists( m_ExeFilename ) && Addr2Line( m_ExeFilename, stack_traces[ i ], buff, BUFF_SIZE) == 0 )
                {
                    fprintf( stderr, "%3d %-32s   %#16" PRIxPTR "   %s", stackLevel, filename, address, buff );
                }
                else
                {
                    fprintf( stderr, "%3d %-32s   %#16" PRIxPTR "   %#" PRIxPTR " + %" PRIuPTR "\n", stackLevel, filename, address, symbolOffset, functionOffset );
                }
            }
            else
            {
                fprintf( stderr, "%s\n", messages[ i ] );
            }
        }
        if (messages) 
        { 
            free( messages ); 
        } 
    }

    void Handler( int sig, siginfo_t * siginfo, void * context )
    {
        switch(sig)
        {
            case SIGSEGV:
                fputs("Caught SIGSEGV: Segmentation Fault\n", stderr);
                break;

            case SIGBUS:
                fputs("Caught SIGBUG: Bus error (bad memory access)\n", stderr);
                break;

            case SIGINT:
                fputs("Caught SIGINT: Interactive attention signal, (usually ctrl+c)\n", stderr);
                break;

            case SIGFPE:
                switch(siginfo->si_code)
                {
                    case FPE_INTDIV:
                        fputs("Caught SIGFPE: (integer divide by zero)\n", stderr);
                        break;
                    case FPE_INTOVF:
                        fputs("Caught SIGFPE: (integer overflow)\n", stderr);
                        break;
                    case FPE_FLTDIV:
                        fputs("Caught SIGFPE: (floating-point divide by zero)\n", stderr);
                        break;
                    case FPE_FLTOVF:
                        fputs("Caught SIGFPE: (floating-point overflow)\n", stderr);
                        break;
                    case FPE_FLTUND:
                        fputs("Caught SIGFPE: (floating-point underflow)\n", stderr);
                        break;
                    case FPE_FLTRES:
                        fputs("Caught SIGFPE: (floating-point inexact result)\n", stderr);
                        break;
                    case FPE_FLTINV:
                        fputs("Caught SIGFPE: (floating-point invalid operation)\n", stderr);
                        break;
                    case FPE_FLTSUB:
                        fputs("Caught SIGFPE: (subscript out of range)\n", stderr);
                        break;
                    default:
                        fputs("Caught SIGFPE: Arithmetic Exception\n", stderr);
                        break;
                }
                break;

            case SIGILL:
                switch(siginfo->si_code)
                {
                    case ILL_ILLOPC:
                        fputs("Caught SIGILL: (illegal opcode)\n", stderr);
                        break;
                    case ILL_ILLOPN:
                        fputs("Caught SIGILL: (illegal operand)\n", stderr);
                        break;
                    case ILL_ILLADR:
                        fputs("Caught SIGILL: (illegal addressing mode)\n", stderr);
                        break;
                    case ILL_ILLTRP:
                        fputs("Caught SIGILL: (illegal trap)\n", stderr);
                        break;
                    case ILL_PRVOPC:
                        fputs("Caught SIGILL: (privileged opcode)\n", stderr);
                        break;
                    case ILL_PRVREG:
                        fputs("Caught SIGILL: (privileged register)\n", stderr);
                        break;
                    case ILL_COPROC:
                        fputs("Caught SIGILL: (coprocessor error)\n", stderr);
                        break;
                    case ILL_BADSTK:
                        fputs("Caught SIGILL: (internal stack error)\n", stderr);
                        break;
                    default:
                        fputs("Caught SIGILL: Illegal Instruction\n", stderr);
                        break;
                }
                break;

            case SIGTERM:
                fputs("Caught SIGTERM: a termination request was sent to the program\n", stderr);
                break;
            case SIGABRT:
                fputs("Caught SIGABRT: usually caused by an abort() or assert()\n", stderr);
                break;
            default:
                break;
        }
        PrintStackTrace( );
        fflush( stderr );
        fflush( stdout );

        _exit( 1 );
    }

    bool Initialise( const char * argv )
    {
        char path[ PATH_MAX ];
        uint32_t size = sizeof( path );
        if ( _NSGetExecutablePath( path, &size ) == 0 )
        {
            if ( ! realpath( path, m_ExeFilename ) )
            {
                strcpy( m_ExeFilename, path );
            }
        }
        else
        {
            strcpy( m_ExeFilename, argv ? argv : "" );
        }

        struct sigaction sig_action = {};
        sig_action.sa_sigaction = Handler;
        sigemptyset(&sig_action.sa_mask);
        sig_action.sa_flags = SA_SIGINFO;

        int toCatch[ ] = {
            SIGSEGV,
            SIGBUS,
            SIGFPE,
            SIGINT,
            SIGILL,
            SIGTERM,
            SIGABRT
        };

        bool okay = true;
        for ( size_t toCatchIx = 0; toCatchIx < PiArraySize( toCatch ); ++toCatchIx )
        {
            okay &= sigaction( toCatch[ toCatchIx ], &sig_action, NULL ) == 0;
        }

        return okay;
    }
}

int main( int argc, char ** argv )
{
    argc = argc;
    argv = argv;

    ExceptionHandler::Initialise( argc > 0 ? argv[ 0 ] : NULL );

    // Do something

    return 0;
}
命名空间异常处理程序
{
charm_ExeFilename[PATH_MAX];
//将cmd store stdout执行到buf中(最大为bufSize)。
int执行(常量字符*cmd,字符*buf,大小\u t bufSize)
{
字符文件名[512];
sprintf(文件名为“%d.tmp”,rand());
如果(FILE*FILE=fopen(文件名,“w”))
{
如果(文件*ptr=popen(cmd,“r”))
{
while(fgets(buf,bufSize,ptr)!=NULL)
{
fprintf(文件“%s”,buf);
}
pclose(ptr);
}
fclose(文件);
取消链接(文件名);
返回0;
}
返回-1;
}
//给定可执行文件的路径和地址,解析符号名和源位置
int Addr2Line(字符常量*常量程序名,无效常量*常量地址,字符*buff,大小\u t buffSize)
{
char addr2line_cmd[512]={0};
sprintf(addr2line_cmd,“atos-d-o%.256s%p”,程序名,addr);
返回执行(addr2line_cmd、buff、buffSize);
}
//检查文件是否存在。
bool文件存在(常量字符*文件名)
{
如果(文件*fh=fopen(文件名,“r”))
{
fclose(fh);
返回true;
}
返回false;
}
//打印堆栈跟踪。
void PrintStackTrace()
{
int trace_size=0;
字符**消息=(字符**)空;
静态const size_t kMaxStackFrames=64;
静态void*堆栈_跟踪[kMaxStackFrames];
trace_size=回溯(堆栈_跟踪,帧);
消息=反向跟踪符号(堆栈跟踪、跟踪大小);
对于(int i=0;inamespace ExceptionHandler
{
    char m_ExeFilename[ PATH_MAX ];

    // Execute cmd store stdout into buf (up to bufSize).
    int Execute( const char * cmd, char * buf, size_t bufSize )
    {
        char filename[ 512 ];
        sprintf( filename, "%d.tmp", rand( ) );

        if ( FILE * file = fopen( filename, "w" ) )
        {
            if ( FILE * ptr = popen( cmd, "r" ) ) 
            {
                while ( fgets( buf, bufSize, ptr ) != NULL )
                {
                    fprintf( file, "%s", buf );
                }
                pclose( ptr );
            }
            fclose( file );

            unlink( filename );

            return 0;   
        }

        return -1;
    }

    // Resolve symbol name and source location given the path to the executable and an address
    int Addr2Line(char const * const program_name, void const * const addr, char * buff, size_t buffSize )
    {
        char addr2line_cmd[512] = {0};
        sprintf( addr2line_cmd, "atos -d -o %.256s %p", program_name, addr ); 
        return Execute( addr2line_cmd, buff, buffSize );
    }

    // Check if file exists.
    bool FileExists( const char * filename )
    {
        if ( FILE * fh = fopen( filename, "r" ) )
        {
            fclose( fh );
            return true;
        }

        return false;
    }

    // Print stack trace.
    void PrintStackTrace( )
    {
        int trace_size = 0;
        char ** messages = ( char ** )NULL;

        static const size_t kMaxStackFrames = 64;
        static void * stack_traces[ kMaxStackFrames ];
        trace_size = backtrace( stack_traces, kMaxStackFrames );
        messages = backtrace_symbols( stack_traces, trace_size );

        for ( int i = 0; i < trace_size; ++i )
        {
            int stackLevel;
            char filename[ 512 ];
            uintptr_t address;
            char symbol[ 512 ];
            uintptr_t symbolOffset;
            uintptr_t functionOffset;
            bool symbolOffsetValid = false;
            bool somethingValid = true;

            if ( sscanf( messages[ i ], "%d%*[ \t]%s%*[ \t]%" SCNxPTR "%*[ \t]%" SCNxPTR "%*[ \t]+%*[ \t]%" SCNuPTR, &stackLevel, filename, &address, &symbolOffset, &functionOffset ) == 5 )
            {
                symbolOffsetValid = true;
            }
            else if ( sscanf( messages[ i ], "%d%*[ \t]%s%*[ \t]%" SCNxPTR "%*[ \t]%s%*[ \t]+%*[ \t]%" SCNuPTR, &stackLevel, filename, &address, symbol, &functionOffset ) == 5 )
            {
            }
            else
            {
                somethingValid = false;
            }

            const size_t BUFF_SIZE = 4096;
            char buff[ BUFF_SIZE ] = { '\0' };

            if ( somethingValid )
            {
                if ( symbolOffsetValid && symbolOffset == 0 )
                {
                    fprintf( stderr, "%3d %-32s   %#16" PRIxPTR "   %#" PRIxPTR " + %" PRIuPTR "\n", stackLevel, filename, address, symbolOffset, functionOffset );
                }
                else if ( FileExists( m_ExeFilename ) && Addr2Line( m_ExeFilename, stack_traces[ i ], buff, BUFF_SIZE) == 0 )
                {
                    fprintf( stderr, "%3d %-32s   %#16" PRIxPTR "   %s", stackLevel, filename, address, buff );
                }
                else
                {
                    fprintf( stderr, "%3d %-32s   %#16" PRIxPTR "   %#" PRIxPTR " + %" PRIuPTR "\n", stackLevel, filename, address, symbolOffset, functionOffset );
                }
            }
            else
            {
                fprintf( stderr, "%s\n", messages[ i ] );
            }
        }
        if (messages) 
        { 
            free( messages ); 
        } 
    }

    void Handler( int sig, siginfo_t * siginfo, void * context )
    {
        switch(sig)
        {
            case SIGSEGV:
                fputs("Caught SIGSEGV: Segmentation Fault\n", stderr);
                break;

            case SIGBUS:
                fputs("Caught SIGBUG: Bus error (bad memory access)\n", stderr);
                break;

            case SIGINT:
                fputs("Caught SIGINT: Interactive attention signal, (usually ctrl+c)\n", stderr);
                break;

            case SIGFPE:
                switch(siginfo->si_code)
                {
                    case FPE_INTDIV:
                        fputs("Caught SIGFPE: (integer divide by zero)\n", stderr);
                        break;
                    case FPE_INTOVF:
                        fputs("Caught SIGFPE: (integer overflow)\n", stderr);
                        break;
                    case FPE_FLTDIV:
                        fputs("Caught SIGFPE: (floating-point divide by zero)\n", stderr);
                        break;
                    case FPE_FLTOVF:
                        fputs("Caught SIGFPE: (floating-point overflow)\n", stderr);
                        break;
                    case FPE_FLTUND:
                        fputs("Caught SIGFPE: (floating-point underflow)\n", stderr);
                        break;
                    case FPE_FLTRES:
                        fputs("Caught SIGFPE: (floating-point inexact result)\n", stderr);
                        break;
                    case FPE_FLTINV:
                        fputs("Caught SIGFPE: (floating-point invalid operation)\n", stderr);
                        break;
                    case FPE_FLTSUB:
                        fputs("Caught SIGFPE: (subscript out of range)\n", stderr);
                        break;
                    default:
                        fputs("Caught SIGFPE: Arithmetic Exception\n", stderr);
                        break;
                }
                break;

            case SIGILL:
                switch(siginfo->si_code)
                {
                    case ILL_ILLOPC:
                        fputs("Caught SIGILL: (illegal opcode)\n", stderr);
                        break;
                    case ILL_ILLOPN:
                        fputs("Caught SIGILL: (illegal operand)\n", stderr);
                        break;
                    case ILL_ILLADR:
                        fputs("Caught SIGILL: (illegal addressing mode)\n", stderr);
                        break;
                    case ILL_ILLTRP:
                        fputs("Caught SIGILL: (illegal trap)\n", stderr);
                        break;
                    case ILL_PRVOPC:
                        fputs("Caught SIGILL: (privileged opcode)\n", stderr);
                        break;
                    case ILL_PRVREG:
                        fputs("Caught SIGILL: (privileged register)\n", stderr);
                        break;
                    case ILL_COPROC:
                        fputs("Caught SIGILL: (coprocessor error)\n", stderr);
                        break;
                    case ILL_BADSTK:
                        fputs("Caught SIGILL: (internal stack error)\n", stderr);
                        break;
                    default:
                        fputs("Caught SIGILL: Illegal Instruction\n", stderr);
                        break;
                }
                break;

            case SIGTERM:
                fputs("Caught SIGTERM: a termination request was sent to the program\n", stderr);
                break;
            case SIGABRT:
                fputs("Caught SIGABRT: usually caused by an abort() or assert()\n", stderr);
                break;
            default:
                break;
        }
        PrintStackTrace( );
        fflush( stderr );
        fflush( stdout );

        _exit( 1 );
    }

    bool Initialise( const char * argv )
    {
        char path[ PATH_MAX ];
        uint32_t size = sizeof( path );
        if ( _NSGetExecutablePath( path, &size ) == 0 )
        {
            if ( ! realpath( path, m_ExeFilename ) )
            {
                strcpy( m_ExeFilename, path );
            }
        }
        else
        {
            strcpy( m_ExeFilename, argv ? argv : "" );
        }

        struct sigaction sig_action = {};
        sig_action.sa_sigaction = Handler;
        sigemptyset(&sig_action.sa_mask);
        sig_action.sa_flags = SA_SIGINFO;

        int toCatch[ ] = {
            SIGSEGV,
            SIGBUS,
            SIGFPE,
            SIGINT,
            SIGILL,
            SIGTERM,
            SIGABRT
        };

        bool okay = true;
        for ( size_t toCatchIx = 0; toCatchIx < PiArraySize( toCatch ); ++toCatchIx )
        {
            okay &= sigaction( toCatch[ toCatchIx ], &sig_action, NULL ) == 0;
        }

        return okay;
    }
}

int main( int argc, char ** argv )
{
    argc = argc;
    argv = argv;

    ExceptionHandler::Initialise( argc > 0 ? argv[ 0 ] : NULL );

    // Do something

    return 0;
}