分享
 
 
 

OutputDebugString()

王朝百科·作者佚名  2011-05-04
窄屏简体版  字體: |||超大  

OutputDebugString ()坚定的 Win32 开发人员可能对OutputDebugString()API 函数比较熟悉,它可以使你的程序和调试器进行交谈。它要比创建日志文件容易,而且所有“真正的”调试器都能使用它。应用程序和调试器交谈的机制相当简单,而本文将揭示整件事情是如何工作的。

本文首先是由以下事件促使的,我们观察到OutputDebugString()在管理员和非管理员用户试图一起工作或游戏时并不总是能可靠地工作(至少在 Win2000 上)。我们怀疑是一些相关的内核对象的权限问题,此间涉略了相当多不得不写下来的信息。

请注意,尽管我们使用了“调试器”这一术语,但不是从调试 API 的意义上来使用的:并没有“单步执行”、“断点”或者“附着到进程”等可以在 MS Visual C 或者一些真正的交互开发环境中找到的东西。从某种意义上来说,任何实现了协议的程序都是“调试器”。可能是一个非常小的命令行工具,或者像来自于SysInternals那帮聪明的家伙们的 DebugView 那样的高级货。应用程序用法构建一条信息并发送之的通常用法是:

sprintf(msgbuf, "Cannot open file %s [err=%ld]

", fname, GetLastError());OutputDebugString(msgbuf);不过在实际环境中我们中的不少人会创建一个前端函数,以允许我们使用 printf 风格的格式化。下面的 odprintf() 函数格式化字符串,确保结尾有一个合适的回车换行(删除原来的行结尾),并且发送信息到调试器。

#include <stdio.h>#include <stdarg.h>#include <ctype.h>void __cdecl odprintf(const char *format, ...){char buf[4096], *p = buf;va_list args;va_start(args, format);p += _vsnprintf(p, sizeof buf - 1, format, args);va_end(args);while ( p > buf && isspace(p[-1]) )*--p = '';*p++ = '

';*p++ = '

';*p = '';OutputDebugString(buf);}于是在代码中使用它就很简单:

...odprintf("Cannot open file %s [err=%ld]", fname, GetLastError());...我们已经这样使用多年了。协议在应用程序和调试器之间传递数据是通过一个 4KB 大小的共享内存块完成的,并有一个互斥量和两个事件对象用来保护对他的访问。下面就是相关的四个内核对象:

对象名称对象类型DBWinMutexMutexDBWIN_BUFFERSection (共享内存)DBWIN_BUFFER_READYEventDBWIN_DATA_READYEvent互斥量通常一直保留在系统中,其他三个对象仅当调试器要接收信息才出现。事实上 - 如果一个调试器发现后三个对象已经存在,它会拒绝运行。

当 DBWIN_BUFFER 出现时,会被组织成以下结构。进程 ID 显示信息的来源,字符串数据填充这 4K 的剩余部分。按照约定,信息的末尾总是包括一个 NULL 字节。

struct dbwin_buffer { DWORD dwProcessId; char data[4096-sizeof(DWORD)]; }; 当OutputDebugString()被应用调用时,它执行以下步骤。注意在任意位置的错误都将放弃整个事情,调试请求被认为是什么也不做(不会发送字符串)。

打开 DBWinMutex 并且等待,直到我们取得了独占访问。映射 DBWIN_BUFFER 段到内存中:如果没有发现,则没有调试器在运行,将忽略整个请求。打开 DBWIN_BUFFER_READY 和 DBWIN_DATA_READY 事件对象。就像共享内存段一样,缺少对象意味着没有可用的调试器。等待 DBWIN_BUFFER_READY 事件对象为有信号状态:表示内存缓冲区不再被占用。大部分时候,这一事件对象一被检查就处于有信号状态,但等待缓冲区就绪不会超过 10 秒(超时将放弃请求)。复制数据直到内存缓冲区中接近 4KB,再保存当前进程 ID。总是放置一个 NULL 字节到字符串结尾。通过设置 DBWIN_DATA_READY 事件对象告诉调试器缓冲区就绪。调试器从那儿取走它。释放互斥量。关闭事件对象和段对象,但保留互斥量的句柄以备后用。在调试器端会简单一点。互斥量根本不需要,如果事件对象和/或共享内存对象已经存在,则假定其他调试器已经在运行。系统中任意时刻只能存在一个调试器。

创建共享内存段以及两个事件对象。如果失败,退出。设置 DBWIN_BUFFER_READY 事件对象,由此应用程序得知缓冲区可用。等待 DBWIN_DATA_READY 事件对象变为有信号状态。从内存缓冲区中提取进程 ID 和 NULL 结尾的字符串。转到步骤 2。这使我们认为这决不是一种低消耗的发送信息的方法,应用程序的运行速度会受到调试器的左右。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有