【问题标题】:What is the point of `static char THIS_FILE[] = __FILE__;`?`static char THIS_FILE[] = __FILE__;` 有什么意义?
【发布时间】:2012-10-27 21:03:54
【问题描述】:

static char THIS_FILE[] = __FILE__; 的意义何在?

简介:它有什么作用?它来自哪里?

MFC 是 Microsoft 的 Windows 原生类库,有一个 DEBUG_NEW 宏,用于跟踪内存分配及其发生的位置(在用户代码中)。

为此,VS 向导将以下代码块放入每个 cpp 文件中:(not 在头文件中)

#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 char 数组的用途。机器没有意义。如果他们将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_NEWmacro 中以复杂的方式完成,而简单的方式可以工作(更好)???


更新:哈!我最近注意到 VS2005 向导没有THIS_FILE 的定义放入生成的 cpp 文件中。

调查了一下,似乎MS前段时间决定不再需要它了,如afxtempl.h定义如下:

#undef THIS_FILE
#define THIS_FILE __FILE__

不过,我想这个问题一直是一样的,为什么它是必要的。 (而且我猜当时内存要求的答案是非常有效的。)


【问题讨论】:

    标签: visual-c++ memory-leaks mfc visual-studio-debugging memory-leak-detector


    【解决方案1】:

    调试分配器在堆块中存储一个指向文件名的指针。只需 4 个字节,而不是让每个分配的块也必须为文件名分配空间。

    请注意,当泄漏的块由 DLL 分配并且在生成泄漏报告时已卸载 DLL 时,这可能会导致调试信息丢失。

    只有字符数组THIS_FILE 保证在翻译单元中始终相同。不是__FILE__,这是字面意思。并且不能保证两个文字具有相同的地址,即使它们具有相同的值,这意味着编译器可以为每次使用 __FILE__ 创建一个不同的文字 - 并耗尽内存。

    【讨论】:

    • 编译器不会已经将它用作参数的文字存储到new 函数调用吗?也许是为了防止多个字面量占用太多空间。
    • 这在旧版本的 VS 中很重要。 MFC 是古老的
    • 我不明白。调试新运算符 (void* AFX_CDECL operator new(size_t nSize, LPCSTR lpszFileName, int nLine); ) 的签名将始终相同,无论我传递它是 __FILE__ 还是 THIS_FILE。那么内存保存在哪里?
    • 只有 THIS_FILE 保证始终相同。不是__FILE__,这是字面意思。并且不保证两个字面量具有相同的地址,即使它们具有相同的值。
    【解决方案2】:

    我相信,我可能是错的,这是在编译的 exe 中描述内存块。如果您要获得异常,这将有所帮助,您可以追溯内存地址链来查找有问题的代码,前提是您知道 dll/exe 加载的地址。

    【讨论】:

      【解决方案3】:

      __FILE__ 在整个文件中是相同的,而__LINE__ 在每一行都发生变化。因此,如果您在文件中有大量调试代码,则不能很好地合并常量的旧编译器会有很多不必要的字符串“filename.ext”副本。您可能可以使用 -fno-merge-constants 之类的东西来检查差异(对不起,这就是它的 gcc CFLAG,不确定 VS)。大多数编译器现在默认合并常量,不需要该定义。

      【讨论】:

      • 是的。几乎是我和@HansPassant 在 cmets 中对他的回答所建立的。或者我认为。
      猜你喜欢
      • 2012-12-26
      • 2010-12-03
      • 2012-03-05
      • 2010-09-18
      • 2020-09-29
      • 2012-09-02
      • 2014-01-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多