_CrtSetDbgFlag

_CrtSetDbgFlag

若要了解有关 Visual Studio 2017 RC 的最新文档,请参阅 Visual Studio 2017 RC 文档

检索或修改的状态_crtDbgFlag标志来控制调试堆管理器 (仅限调试版本) 的分配行为。

语法

      int _CrtSetDbgFlag(   
   int newFlag   
);  

参数

newFlag 新状态的_crtDbgFlag

返回值

返回的前一状态_crtDbgFlag

备注

_CrtSetDbgFlag函数允许应用程序来控制调试堆管理器通过修改的位域跟踪内存分配的方式_crtDbgFlag标志。 通过设置位(打开),该应用程序可指示调试堆管理器执行特殊的调试操作,包括在应用程序退出时检查内存泄露并报告是否找到任何内存泄露、通过指定已释放的内存块应保留在堆的链接列表中来模拟内存不足情况,以及通过在每次分配请求时检查每个内存块来验证该堆的完整性。 当_DEBUG未定义,则调用_CrtSetDbgFlag在预处理过程中删除。

下表列出的位域_crtDbgFlag并说明它们的行为。 因为设置位将导致诊断输出增加、程序执行速度减慢,因此在默认情况下不会设置这些位(已关闭)。 有关详细信息,有关这些位域,请参阅堆状态报告函数。

位域

默认

描述

_CRTDBG_ALLOC_MEM_DF

打开

打开:启用调试堆分配并使用内存块类型标识符,例如 _CLIENT_BLOCK。 关闭︰ 将新的分配添加到堆的链接列表,但设置阻止类型设置为_IGNORE_BLOCK。 还可以与任何堆频率检查宏组合。

_CRTDBG_CHECK_ALWAYS_DF

关闭

打开︰ 调用_CrtCheckMemory在每次分配和解除分配请求。 关闭:必须显式调用 _CrtCheckMemory。 设置此标志后,堆频率检查宏不会产生任何影响。

_CRTDBG_CHECK_CRT_DF

关闭

打开:包括泄漏检测和内存状态差异操作中的 _CRT_BLOCK 类型。 关闭:这些操作将忽略运行时库在内部使用的内存。 还可以与任何堆频率检查宏组合。

_CRTDBG_DELAY_FREE_MEM_DF

关闭

打开︰ 将已释放的内存块在堆链接列表中,将它们分配_FREE_BLOCK键入,然后使用字节值 0xDD 填充它们。 关闭:不要将已释放的块保留在堆链接列表中。 还可以与任何堆频率检查宏组合。

_CRTDBG_LEAK_CHECK_DF

关闭

打开︰ 执行自动泄露检查在程序退出时通过调用_CrtDumpMemoryLeaks ,则生成错误报告,如果应用程序未能释放其所分配的所有内存。 关闭:不要在程序退出时自动执行泄露检查。 还可以与任何堆频率检查宏组合。

堆频率检查宏

您可以指定何种频率 C 运行库执行的调试堆的验证 (_CrtCheckMemory) 基于对的调用次数mallocrealloc免费,和_msize

然后,_CrtSetDbgFlag 将检查某个值的 newFlag 参数较高的 16 位。 指定的值是数mallocrealloc免费,和_msize调用之间_CrtCheckMemory调用。 为此,将提供四个预定义的宏。

对 _CrtCheckMemory 的调用之间的 malloc、realloc、free 和 _msize 调用数

_CRTDBG_CHECK_EVERY_16_DF

16

_CRTDBG_CHECK_EVERY_128_DF

128

_CRTDBG_CHECK_EVERY_1024_DF

1024

_CRTDBG_CHECK_DEFAULT_DF

0(默认情况下,不存在堆检查)

默认情况下,_CrtCheckMemory将调用一次调用的每个 1024 次malloc realloc免费,和_msize

例如,可以指定 1 次堆检查每个 16 mallocrealloc免费,和_msize操作替换为以下代码︰

#include <crtdbg.h>  
int main( )  
{  
int tmp;  
  
// Get the current bits  
tmp = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);  
  
// Clear the upper 16 bits and OR in the desired freqency  
tmp = (tmp & 0x0000FFFF) | _CRTDBG_CHECK_EVERY_16_DF;  
  
// Set the new bits  
_CrtSetDbgFlag(tmp);  
}  

在指定 _CRTDBG_CHECK_ALWAYS_DF 时,忽略 newFlag 参数较高的 16 位。 在这种情况下,_CrtCheckMemory称为您每次调用mallocrealloc免费,和_msize

newFlag是要应用于的新状态_crtDbgFlag也是每位域的值的组合。

更改一个或多个位域并创建标志的新状态

  1. 调用_CrtSetDbgFlagnewFlag等于_CRTDBG_REPORT_FLAG以获取当前_crtDbgFlag状态,并在临时变量中存储返回的值。
  2. 通过对带有相应位掩码的临时变量(在应用程序代码中由清单常量显示)进行 OR 运算来打开任何位。
  3. 请关闭其他位由AND运算结果的变量进行按位相应位掩码。
  4. 调用_CrtSetDbgFlagnewFlag要设置的新状态的临时变量中存储的值等于_crtDbgFlag

以下代码演示如何通过在堆链接列表中保留已释放的内存块来模拟内存不足情况,以及如何阻止在每个分配请求时都调用 _CrtCheckMemory

// Get the current state of the flag  
// and store it in a temporary variable  
int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );  
  
// Turn On (OR) - Keep freed memory blocks in the  
// heap's linked list and mark them as freed  
tmpFlag |= _CRTDBG_DELAY_FREE_MEM_DF;  
  
// Turn Off (AND) - prevent _CrtCheckMemory from  
// being called at every allocation request  
tmpFlag &= ~_CRTDBG_CHECK_ALWAYS_DF;  
  
// Set the new state for the flag  
_CrtSetDbgFlag( tmpFlag );  

有关内存管理和调试堆的概述,请参阅CRT 调试堆详细信息。

若要禁用有标志_CrtSetDbgFlag函数,您应该AND的变量进行的按位的位掩码。

如果newFlag不是有效的值,此函数将调用无效参数处理程序,如中所述参数验证。 如果允许执行继续,则该函数会将 errno 设置为 EINVAL 并返回之前的 _crtDbgFlag 状态。

要求

例程

必需的标头

_CrtSetDbgFlag

<crtdbg.h>

有关更多兼容性信息,请参阅“简介”中的 Compatibility 。

调试版本C 运行时库仅。

示例

// crt_crtsetdflag.c  
// compile with: /c -D_DEBUG /MTd -Od -Zi -W3 /link -verbose:lib /debug  
/*  
 * This program concentrates on allocating and freeing memory  
 * blocks to test the functionality of the _crtDbgFlag flag..  
 */  
  
#include <string.h>  
#include <malloc.h>  
#include <crtdbg.h>  
  
int main( )  
{  
        char *p1, *p2;  
        int tmpDbgFlag;  
  
        _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );  
        _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDERR );  
        /*  
         * Set the debug-heap flag to keep freed blocks in the  
         * heap's linked list - This will allow us to catch any  
         * inadvertent use of freed memory  
         */  
        tmpDbgFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);  
        tmpDbgFlag |= _CRTDBG_DELAY_FREE_MEM_DF;  
        tmpDbgFlag |= _CRTDBG_LEAK_CHECK_DF;  
        _CrtSetDbgFlag(tmpDbgFlag);  
  
        /*  
         * Allocate 2 memory blocks and store a string in each  
         */  
        p1 = malloc( 34 );  
        p2 = malloc( 38 );  
        strcpy_s( p1, 34, "p1 points to a Normal allocation block" );  
        strcpy_s( p2, 38, "p2 points to a Client allocation block" );  
  
        /*  
         * Free both memory blocks  
         */  
        free( p2 );  
        free( p1 );  
  
        /*  
         * Set the debug-heap flag to no longer keep freed blocks in the  
         * heap's linked list and turn on Debug type allocations (CLIENT)  
         */  
        tmpDbgFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);  
        tmpDbgFlag |= _CRTDBG_ALLOC_MEM_DF;  
        tmpDbgFlag &= ~_CRTDBG_DELAY_FREE_MEM_DF;  
        _CrtSetDbgFlag(tmpDbgFlag);  
  
        /*  
         * Explicitly call _malloc_dbg to obtain the filename and   
         * line number of our allocation request and also so we can   
         * allocate CLIENT type blocks specifically for tracking  
         */  
        p1 = _malloc_dbg( 40, _NORMAL_BLOCK, __FILE__, __LINE__ );  
        p2 = _malloc_dbg( 40, _CLIENT_BLOCK, __FILE__, __LINE__ );  
        strcpy_s( p1, 40, "p1 points to a Normal allocation block" );  
        strcpy_s( p2, 40, "p2 points to a Client allocation block" );  
  
        /*  
         * _free_dbg must be called to free the CLIENT block  
         */  
        _free_dbg( p2, _CLIENT_BLOCK );  
        free( p1 );  
  
        /*  
         * Allocate p1 again and then exit - this will leave unfreed  
         * memory on the heap  
         */  
        p1 = malloc( 10 );  
}  

.NET Framework 等效项

不适用。 若要调用标准 C 函数,请使用 PInvoke。 有关更多信息,请参见 平台调用示例

另请参阅

调试例程 _crtDbgFlag _CrtCheckMemory

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏后台全栈之路

在 C/C++ 异步 I/O 中使用 MariaDB 的非阻塞接口

对 C/C++,MySQL 提供的库传统上都是阻塞操作,因此适合多线程 / 进程服务器架构编程。但是如果用 C/C++ 编写服务器,往往对性能会有极致要求,此时...

4202
来自专栏企鹅号快讯

渗透技巧——”隐藏”注册表的创建

0x00 前言 知名恶意软件Poweliks曾使用过的一个后门技术,在注册表启动位置创建一个特殊的注册表键值,通过mshta来执行payload 对于这个特殊的...

1908
来自专栏北京马哥教育

最全整理 | 121个Ubuntu终端常用快捷键

Ubuntu中的许多操作在终端(Terminal)中十分的快捷,记住一些快捷键的操作更得心应手。在Ubuntu中打开终端的快捷键是Ctrl+Alt+T。其他的一...

26912
来自专栏MasiMaro 的技术博文

PE文件解析器的编写(二)——PE文件头的解析

之前在学习PE文件格式的时候,是通过自己查看各个结构,自己一步步计算各个成员在结构中的偏移,然后在计算出其在文件中的偏移,从而找到各个结构的值,但是在使用C语言...

772
来自专栏葡萄城控件技术团队

绑定Oracle Database 到 ActiveReport

ActiveReport 可以和多种数据源交互,包括OLEDB, SQL, XML和集合对象。 在本文中我们将阐述如何绑定Oracle 数据库到 Active...

1869
来自专栏debugeeker的专栏

《coredump问题原理探究》Linux x86版6.5节虚函数的coredump例子

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xuzhina/article/detai...

440
来自专栏较真的前端

关于客户端存储的前端面试题总结

2077
来自专栏deed博客

十天学会php详细文字教程_入门至精通

1212
来自专栏Linux驱动

18.Llinux-触摸屏驱动(详解)

本节的触摸屏驱动也是使用之前的输入子系统 1.先来回忆之前第12节分析的输入子系统 其中输入子系统层次如下图所示, ? 其中事件处理层的函数都是通过input_...

2169
来自专栏Android 研究

Android跨进程通信IPC之8——Binder驱动

原本是没有这篇文章的,因为原来写Binder的时候没打算写Binder驱动,不过我发现后面大量的代码都涉及到了Binder驱动,如果不讲解Binder驱动,可能...

922

扫码关注云+社区