我正在尝试用函数跟踪构建我自己的异常类(我想知道调用到异常的所有函数的文件和行号,以及它们总共调用函数的次数)。
函数跟踪在构建它时似乎是有效的,但是当试图正确地使用它时,我已经被分割错误包围了。我跟踪了其中的一些错误(愚蠢的错误,比如忘记返回任何东西或丢弃符号),但是这个错误正在折磨我--而且我还不知道我是如何得到我看到的调试语句的。
我希望我的代码需要很多改进(对于我绝对不应该做的事情,我会感激你的建议或严厉的评论),但是谁能帮我弄清楚这里发生了什么呢?我试图利用我的FunctionTrace类,并抛出cout语句,在这些语句中,我认为它们是有用的,但我却一无所获。
我包括一个去掉的int ()、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__);
#endifMathsException.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}
};
#endifgdb输出
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.编辑:添加了我错过的FunctionTrace.hpp的最后几行
我想看看编译器是否会帮助我
在返回可能为空的对象之前添加了一些ifs --我仍然得到相同的seg错误,但是gdb输出是不同的(尽管如此)
进度:更改调用,如
std::vector<FunctionCallDetails>::iterator fnCallsIter = fnTraceMgr.getAllFunctionCalls().begin();至
std::vector<FunctionCallDetails> fnCalls = fnTraceMgr.getAllFunctionCalls();
std::vector<FunctionCallDetails>::iterator fnCallsIter = fnCalls.begin();(并更新for循环)删除了seg错误;不知何故,我的迭代器一直指向某个愚蠢的地方。
并且取消最后一步,我没有一个seg错误(我以前做过的)
发布于 2012-10-24 01:49:23
您正在返回对FunctionTraceManager::gatherFunctionCalls中的局部变量的引用。
引用非常类似于指针,返回引用基本上返回变量的地址。但是,由于函数中的局部变量在函数返回时超出作用域,因此不能引用这些变量(通过指针或引用)。这是一种未定义的行为,有时可能会起作用,但经常会发生奇怪的事情,比如程序崩溃。
https://stackoverflow.com/questions/13041820
复制相似问题