首页 文章

分段错误 - 奇怪的调试语句

提问于
浏览
0

我正在尝试使用函数跟踪构建我自己的异常类(我想知道调用异常的所有函数的文件和行号,以及它们总共调用函数的次数)

函数跟踪似乎在构建它时起作用,但是当试图正确使用它时,我被分段错误所困扰 . 我跟踪了其中的一些(愚蠢的错误,比如忘记返回任何东西或丢掉&符号)但是这个让我感到害怕 - 我还不知道我是如何得到我所看到的调试语句的 .

我希望我的代码需要很大的改进(我会感激任何关于我绝对不应该做的建议或严厉的评论)但是任何人都可以帮我弄清楚这里有什么 . 我试图利用我的FunctionTrace类,并抛出cout语句,我认为它们很有用,但我无处可去 .

我包括一个剥离的int main(),FunctionTrace . {c,h} pp,MathsException.hpp(还没有.cpp),以及gdb的输出(仍在学习使用它)

main.cpp中

#include <iostream>
#include "FunctionTrace.hpp"
#include "MathsException.hpp"

using namespace std;

int main(int argc, char* argv[])
{
    LOG_FUNC_CALL
    try
    {
        std::string test = "";
        MathsException oExc(test);
        throw oExc;
    }
    catch(MathsException& iException)
    {
        iException.what();
    }
    return 0;
}

FunctionTrace.cpp

#include "FunctionTrace.hpp"
#include <vector>
#include <string>
#include <iostream>
#include <stdio.h>

static int countDebugStatic = 0; //TODO delete me!

int& FunctionCallDetails::getLine(){return lineNumber;}

const char* FunctionCallDetails::getFile(){return file;}

int& FunctionCallDetails::getNoOfTimesCalled(){return noOfTimesCalled;}

FunctionTrace::FunctionTrace(const int iLineNumber, const char* iFile)
{
    FunctionTraceManager& fnTraceMgr = FunctionTraceManager::getInstance();

    int oTimesCalled = ++fnTraceMgr.getAllTimesCalled()[std::make_pair(iLineNumber, iFile)];
    fnTraceMgr.getAllFunctionCalls().push_back(FunctionCallDetails(iLineNumber, iFile, oTimesCalled));
}

std::vector<std::string>& FunctionTraceManager::gatherFunctionCalls()
{
    FunctionTraceManager& fnTraceMgr = FunctionTraceManager::getInstance();
    std::vector<FunctionCallDetails>::iterator fnCallsIter =  fnTraceMgr.getAllFunctionCalls().begin();
    std::vector<std::string> oFnDetails;
    for(; fnCallsIter != fnTraceMgr.getAllFunctionCalls().end(); ++fnCallsIter)
    {
        countDebugStatic++;
        std::cout << "count: " << countDebugStatic << "\n";
        std::string fnDetail = "Function at line: ";
        char lineCalled[11]; //I'd never live long enough to generate this many lines of code in one file
        snprintf(lineCalled, 10, "%d", fnCallsIter->getLine());
        fnDetail += lineCalled;
        fnDetail += ", in file: ";
        fnDetail += fnCallsIter->getFile();
        fnDetail += " called: ";
        char noOfTimesCalled[11]; //log(2^32)/log(10) = 9.~~ (need a null char) 
        snprintf(noOfTimesCalled, 10, "%d", fnCallsIter->getNoOfTimesCalled());
        fnDetail += noOfTimesCalled;
        fnDetail += " times.";
        oFnDetails.push_back(fnDetail);
        std::cout << "fnDetail: " << fnDetail << "\n";
    }
    if(oFnDetails.size() > 0)
    {
        return oFnDetails;
    }
    else
    {
        oFnDetails.push_back("");
        return oFnDetails;
    }
}


FunctionTrace::~FunctionTrace()
{
    FunctionTraceManager& fnTraceMgr = FunctionTraceManager::getInstance();
    fnTraceMgr.getAllFunctionCalls().pop_back();
}

FunctionTrace.hpp

#ifndef FUNCTION_TRACE_HPP
#define FUNCTION_TRACE_HPP

#include <vector>
#include <string>
#include <map>
#include <iostream>

class FunctionCallDetails
{
    int lineNumber;
    const char* file;
    int noOfTimesCalled;
    public:
        FunctionCallDetails(const int iLineNumber, const char* iFile, int iTimesCalled): lineNumber(iLineNumber), file(iFile), noOfTimesCalled(iTimesCalled){};
        int& getLine();
        const char* getFile();
        int& getNoOfTimesCalled();
};

class FunctionTraceManager
{
    //singleton
    std::vector<FunctionCallDetails> functionCalls;
    std::map<std::pair<const int,const char*>,int> timesCalled;

    FunctionTraceManager(){}
    FunctionTraceManager(FunctionTraceManager const&){}
    ~FunctionTraceManager(){}
    void operator = (FunctionTraceManager const&){}

    public:
        //this method will be the only way to get a FnTraceMgr object, and once statically created, further calls will retrieve the first (and only) FnTraceMgr
        //Object created.
        static FunctionTraceManager& getInstance()
        {
            static FunctionTraceManager fnTraceMgrInstance;
            return fnTraceMgrInstance;
        }
        std::vector<FunctionCallDetails>& getAllFunctionCalls()
        std::map<std::pair<const int,const char*>,int>& getAllTimesCalled()
        {
            if(functionCalls.size() > 0)
            {
                return functionCalls;
            }
            else
            {
                functionCalls.push_back(FunctionCallDetails(-1,"",-1));
                return functionCalls;
            }
        }
        std::map<std::pair<const int,const char*>,int>& getAllTimesCalled(){return timesCalled;}
        std::vector<std::string>& gatherFunctionCalls();
};
class FunctionTrace
{
    public:
        FunctionTrace(const int iLineNumber, const char* iFile);
        ~FunctionTrace();
};

#define LOG_FUNC_CALL FunctionTrace functionTrace(__LINE__,__FILE__);
#endif

MathsException.hpp

#ifndef MATHS_EXCEPTION_HPP
#define MATHS_EXCEPTION_HPP
#include <exception>
#include "FunctionTrace.hpp"



#include <iostream>
class MathsException : public std::exception
{
    std::string errMsg;
    public:
        MathsException() throw() { LOG_FUNC_CALL };
        MathsException(const std::string iMsg): errMsg(iMsg){ LOG_FUNC_CALL }
        MathsException(const char* iMsg): errMsg(iMsg){ LOG_FUNC_CALL }
        std::string appendFunctionTracing()
        {
            LOG_FUNC_CALL
            std::string oStr = "";
            FunctionTraceManager& fnTraceMgr = FunctionTraceManager::getInstance();

            std::cout << "Why am I not seeing this at all !???";
            std::cout << "Why am I only seeing this once !???  fnTraceMgr.gatherFunctionCalls().size(): " << fnTraceMgr.gatherFunctionCalls().size() << "\n";
            std::vector<std::string>::iterator fnCallsIter = fnTraceMgr.gatherFunctionCalls().begin();
            for(; fnCallsIter != fnTraceMgr.gatherFunctionCalls().end(); ++fnCallsIter)
            {
                oStr += *fnCallsIter;
                oStr += "\n";
            }
            oStr += errMsg;
            return oStr;
        }
        void what()
        {
            LOG_FUNC_CALL
            std::cout << appendFunctionTracing();
        }

        ~MathsException() throw(){LOG_FUNC_CALL}
};

#endif

gdb输出

greg@greg-Aspire-5742:~/Documents/MMath/c++projects/2012_revision/Solver$ gdb Solver
GNU gdb (Ubuntu/Linaro 7.3-0ubuntu2) 7.3-2011.08
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-linux-gnu".
For bug reporting instructions, please see:
<http://bugs.launchpad.net/gdb-linaro/>...
Reading symbols from /home/greg/Documents/MMath/c++projects/2012_revision/Solver/Solver...done.
(gdb) r
Starting program: /home/greg/Documents/MMath/c++projects/2012_revision/Solver/Solver 
Why am I not seeing this at all !???count: 1
fnDetail: Function at line: -1, in file:  called: -1 times.
count: 2
fnDetail: Function at line: 10, in file: main.cpp called: 1 times.
count: 3
fnDetail: Function at line: 35, in file: MathsException.hpp called: 1 times.
count: 4
fnDetail: Function at line: 18, in file: MathsException.hpp called: 1 times.
Why am I only seeing this once !???  fnTraceMgr.gatherFunctionCalls().size(): 4
count: 5
fnDetail: Function at line: -1, in file:  called: -1 times.
count: 6
fnDetail: Function at line: 10, in file: main.cpp called: 1 times.
count: 7
fnDetail: Function at line: 35, in file: MathsException.hpp called: 1 times.
count: 8
fnDetail: Function at line: 18, in file: MathsException.hpp called: 1 times.
count: 9
fnDetail: Function at line: -1, in file:  called: -1 times.
count: 10
fnDetail: Function at line: 10, in file: main.cpp called: 1 times.
count: 11
fnDetail: Function at line: 35, in file: MathsException.hpp called: 1 times.
count: 12
fnDetail: Function at line: 18, in file: MathsException.hpp called: 1 times.

Program received signal SIGSEGV, Segmentation fault.
0xb7f6e478 in std::string::append(std::string const&) () from /usr/lib/i386-linux-gnu/libstdc++.so.6
(gdb) info locals
No symbol table info available.
(gdb) bt
#0  0xb7f6e478 in std::string::append(std::string const&) () from /usr/lib/i386-linux-gnu/libstdc++.so.6
#1  0x0804b564 in operator+= (__str=..., this=0xbffff138) at /usr/include/c++/4.6/bits/basic_string.h:925
#2  MathsException::appendFunctionTracing (this=0x80530d8) at MathsException.hpp:27
#3  0x0804989b in what (this=0x80530d8) at MathsException.hpp:36
#4  main (argc=Cannot access memory at address 0x1
) at main.cpp:19
(gdb) info locals
No symbol table info available.
(gdb) up
#1  0x0804b564 in operator+= (__str=..., this=0xbffff138) at /usr/include/c++/4.6/bits/basic_string.h:925
925       { return this->append(__str); }
(gdb) info locals
No locals.
(gdb) up
#2  MathsException::appendFunctionTracing (this=0x80530d8) at MathsException.hpp:27
27              oStr += *fnCallsIter;
(gdb) info locals
functionTrace = {<No data fields>}
oStr = {static npos = <optimized out>, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x80523ac ""}}
fnCallsIter = {_M_current = 0x8053310}
(gdb) up
#3  0x0804989b in what (this=0x80530d8) at MathsException.hpp:36
36          std::cout << appendFunctionTracing();
(gdb) info locals
functionTrace = {<No data fields>}
(gdb) up
#4  main (argc=Cannot access memory at address 0x1
) at main.cpp:19
19      iException.what();
(gdb) info locals
iException = @0x80530d8
functionTrace = {<No data fields>}
(gdb) up
Initial frame selected; you cannot go up.

Edits: 添加在FunctionTrace.hpp的底部几行我错过了

如果编译器能帮助我,我可以查看所有参数 - 仍然没用

在我可能返回空对象之前添加了一些ifs - 我仍然得到相同的seg错误但是gdb输出不同(尽管仍然很奇怪)

progress: 更改电话如

std::vector<FunctionCallDetails>::iterator fnCallsIter =  fnTraceMgr.getAllFunctionCalls().begin();

std::vector<FunctionCallDetails> fnCalls =  fnTraceMgr.getAllFunctionCalls();
std::vector<FunctionCallDetails>::iterator fnCallsIter =  fnCalls.begin();

(并更新for循环)删除了seg错误;不知何故,我的迭代器一直指向某个愚蠢的地方

并撤消最后一步我没有得到段错误(以前我做过)

1 回答

  • 1

    您将在 FunctionTraceManager::gatherFunctionCalls 中返回对局部变量的引用 .

    引用很像指针,返回引用基本上返回变量的地址 . 但是,当函数返回时,函数中的局部变量超出范围,因此无法引用这些变量(通过指针或引用) . 这是未定义的行为,有时可能有效,但通常会发生奇怪的事情,比如程序崩溃 .

相关问题