static char THIS_FILE[] = __FILE__;
有什么意义?MFC,Microsoft Windows 的本机类库,有一个
DEBUG_NEW
宏,用于跟踪内存分配及其发生的位置(在用户代码中)。
为此,VS 向导将以下代码块放入每个 cpp 文件中:(不是在头文件中)
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
调试新宏定义为(在
afx.h
中):
#define DEBUG_NEW new(THIS_FILE, __LINE__)
整个机器将产生有意义的泄漏检测输出,例如:
Detected memory leaks!
Dumping objects ->
f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\strcore.cpp(141) : {615} normal block at 0x04081CE0, 56 bytes long.
Data: <¬9Í] > AC 39 CD 5D 13 00 00 00 13 00 00 00 01 00 00 00
c:\my\dev\path\myfile.cpp(237) : {614} normal block at 0x04087FC0, 4 bytes long.
Data: <ð > F0 1C 08 04
Object dump complete.
让我困惑的是
THIS_FILE
字符数组的用途。机械没有意义。如果他们将 DEBUG_NEW
定义为:
#define DEBUG_NEW new(__FILE__, __LINE__)
他们可以将其放在标头中并完成它,而不是在每个文件中都包含该
ifdef
块。
那么,
THIS_FILE
有什么意义?
(顺便说一句,这正是 MS 的 CRT 对
malloc
和 _malloc_dbg
所做的事情,其中调试宏在标头 crtdbg.h
中定义为:
#define malloc(s) _malloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__)
)
再说一遍,为什么在 MFC
DEBUG_NEW
宏中要采用复杂的方式来完成,而简单的方法可以工作(更好)???
更新:哈!我最近注意到VS2005向导没有将
THIS_FILE
的定义放入生成的cpp文件中。
调查一下,似乎MS不久前就决定不再需要了,如
afxtempl.h
中定义了以下内容:
#undef THIS_FILE
#define THIS_FILE __FILE__
不过,我想问题仍然是一样的,为什么它是必要的。 (我想当时的内存需求答案是非常有效的。)
调试分配器在堆块中存储指向文件名的指针。 只需 4 个字节,而不是让每个分配的块也必须为文件名分配空间。
请注意,当泄漏块由 DLL 分配并且 DLL 在生成泄漏报告时已卸载时,这可能会导致调试信息丢失。
仅保证字符数组
THIS_FILE
在翻译单元中始终相同。不是__FILE__
,这是字面意思。并且不能保证两个文字具有相同的地址,即使它们具有相同的值,这意味着编译器可以为每次使用 __FILE__
创建不同的文字 - 并耗尽内存。
__FILE__
在整个文件中都是相同的,而 __LINE__
在每一行都发生变化。 因此,如果文件中有大量调试代码,则无法很好地合并常量的旧编译器将产生大量不必要的字符串“filename.ext”副本。 您也许可以使用 -fno-merge-constants 之类的东西来检查差异(抱歉,这是 gcc CFLAG,不确定 VS)。 大多数编译器现在默认合并常量,使得该定义变得不必要。
我相信,我可能是错的,这是在编译的 exe 内描绘内存块。如果您要获得异常,这将有所帮助,您可以跟踪内存地址链以找到有问题的代码,前提是您知道 dll/exe 加载的地址。
我的笔记:
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Use of THIS_FILE
// ================
// Each time __FILE__ is used, the compiler creates a new instance of the
// string, resulting in multiple strings with the same content. The compiler,
// could, if string pooling is enabled, eliminate all duplicate strings and keep
// only one.
//
// In VC 6.0:
// "/Gf" option: String pooling is enabled, eliminating duplicate strings.
// "/GF" option: Strings are placed in read-only memory so become immutable.
//
// THIS_FILE might be defined as:
//
// #define THIS_FILE __FILE__
// This achieves nothing. THIS_FILE is preprocessed into __FILE__.
//
// static char THIS_FILE[]=__FILE__;
// This creates a single instance of a mutable string. When referenced,
// THIS_FILE is replaced with a pointer to the string.
//
// static const char THIS_FILE[]=__FILE__;
// This creates an immutable copy of the string, making it a literal, so it is
// a candidate for string pooling. Except each instance of THIS_FILE in
// different files represents a unique path and filename, so there is nothing
// to pool.
//
// Note that "static" limits file scope to the current file and prevents linkage
// issues.
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////