QAVisual C++ 7.1Visual Studio 6Visual C++ 7.0Windows 2003Windows 2000Visual C++ 6.0Windows XPMFC中级开发Visual StudioWindowsC++
函数调用序列跟踪类






4.56/5 (12投票s)
2003年8月16日
2分钟阅读

65665

1147
一个用于跟踪函数调用顺序的类。
引言
在复杂的应用程序中,有时需要处理大量的消息,并且有大量的函数用于处理请求和事件。有时很难看出给定函数调用了哪些函数,哪些函数会导致对特定函数的调用,以及所有这些函数的调用顺序。如果某个程序员要继续另一个程序员未完成的工作,那么在一个文档记录不完善的系统中,这将是一场噩梦。即使是之前完成所有这些工作的程序员也可能会感到困惑。我在我的一个项目中遇到了这个问题。我在互联网上搜索解决方案,但不幸的是,我没有找到,所以我开始自己做。我编写了一个类来跟踪应用程序中的方法,并将所有序列以可读的格式记录到一个文件中。
想法
我的解决方案的想法是使用一个小型类的全局对象,该类具有一些静态成员函数和静态成员变量。在应用程序的早期阶段(例如,在应用程序类的构造函数中),我们指定将保存序列日志的文件。这是通过一个静态函数完成的。该类包含一些私有静态成员变量来维护当前的调用级别。在函数开始时,使用构造函数在堆栈中实例化此类的实例,构造函数以应记录的文本作为参数。在函数结束时,此类的实例将超出范围,因此将调用该类的析构函数,并且级别将降低。
实现
以下是 SequenceTracer
类的头文件
// SequenceTracer.h #ifndef _SEQUENCE_TRACER #define _SEQUENCE_TRACER #include <fstream> // for std::ofstream class SequenceTracer { public: static void Start(const char * fileName); // Set the file name and start SequenceTracer(const char * text); // The only constructor virtual ~SequenceTracer(); protected: static int Stack[256]; // The stack maintaing sequence numbers static int Level; // The current level in the stack static std::ofstream * OutStream; // The always open output stream }; #endif //_SEQUENCE_TRACER
这是该类的实现文件
// SequenceTracer.cpp #include "SequenceTracer.h" ////////////////////////////////////////////////////////////////////// int SequenceTracer::Level; std::ofstream * SequenceTracer::OutStream; int SequenceTracer::Stack[256]; ////////////////////////////////////////////////////////////////////// void SequenceTracer::Start(const char *fileName) { OutStream = new std::ofstream (fileName); } ////////////////////////////////////////////////////////////////////// SequenceTracer::SequenceTracer(const char * text) { if (!OutStream) // Outstream should be initialized return; for (int i = 0; i < Level; i++) *OutStream << '\t'; // Make indentation Stack[Level]++; // Increment the sequence number for (i = 0; i < Level, Stack[i] > 0; i++) *OutStream << Stack[i] << '.'; // Print the sequence number *OutStream << " "; // Add a space *OutStream << text << "\n"; // Write the text followed by newline Level++; // Increase the level } ////////////////////////////////////////////////////////////////////// SequenceTracer::~SequenceTracer() { Stack[Level] = 0; // Reset the sequence number Level--; // Decrease the level if (Level < 0) // If we are finished { delete OutStream; // Write to the file and delete stream OutStream = 0; // Reset the stream pointer } } //////////////////////////////////////////////////////////////////////
使用该类
使用此类非常简单,只需三个步骤
- 在要跟踪函数序列的 CPP 文件中包含 SequencTracer.h
- 在应用程序的早期阶段(例如,应用程序构造函数)调用静态函数
Start
并将要创建的文件名提供给此函数,该文件将存储所有序列 - 在你想了解其用法的任何函数的开头,在堆栈中实例化一个该类的对象
在运行应用程序并且级别小于 0 之后,您可以查看序列文件的内容。它看起来像
我专门制作了一个应用程序来测试这个类。我制作了两个辅助宏,以进一步简化该类的使用
#ifdef _DEBUG #define SEQ_TRACE(txt) SequenceTracer unique_variable_name##__LINE__ (txt) #define SEQ_START(fileName) SequenceTracer::Start(fileName) #else #define SEQ_TRACE(txt) #define SEQ_START(fileName) #endif // Thanks to Michael Dunn for ##__LINE__
历史
- 2003 年 8 月 16 日:文章已提交,小幅更新。