Windows进程内标准输出重定向及其在程序调试上的应用

告别静默崩溃!Qt程序调试输出全攻略:从qDebug到控制台重定向 本文全面解析Qt程序调试输出的配置与高级捕获技术,从基础的qDebug使用到控制台重定向,涵盖Windows、Linux和macOS三大平台。通过.pro文件配置CONFIG += console启用控制台输出,并介绍日志分级、过滤及重定向到文件或网络服务器的方案,帮助开发者高效定位和解决程序崩溃问题。 阅读详情
  1. 一、如何实现  
  2.   
  3. 打印调试信息的方法有很多,最常用的是使用标准输出设备(如printf、cout等),也可以用OutPutDebugString输出、用 DebugView工具查看,还可以写入日志文件。如果程序运行需要记录日志(log),往往需要打开个文件,或许是写入系统事件、用系统的事件查看器查看。  
  4.   
  5. 应用程序打印调试信息、日志的方法往往是确定的,但如果是要编写一个模块或者说组件,那样的输出信息应该写入哪里呢?或者说程序本身对此也没有明确需求的话,那该怎么办呢?  
  6.   
  7. 可喜的是一个进程的标准输出是可以重定向的,所以我建议把调试信息直接打到标准输出上,这样代码中可以统一使用cout或者printf,然后根据需要将标准输出重定向。  
  8.   
  9. Linux 中重定向标准输出就容易了,因为有强大的dup2函数。而对于Windows的重定向,貌似往往是用于子进程的,在用CreateProcess创建子进程时设置子进程的标准输出句柄。而我们想要的是重定向自己这个进程的标准输出,那个用不上。我在MSDN中也没找到类似dup2的Win32 API函数,只有一个DuplicateHandle函数,这相当于linux中的dup,也用不上。  
  10.   
  11. 这里顺便提下,SetStdHandle是不能实现重定向的。这个函数的功能是将某句柄指向标准设备,并不能将标准设备句柄重定向到另外的句柄。  
  12.   
  13. 于是我就想到,Windows不是支持一部分POSIX标准的吗。于是我找到了一个CRT的函数,叫_dup2,看起来是不是特眼熟,对了,这就是Windows中dup2的兼容版本。  
  14.   
  15. 值得注意的是,_dup2以及与此相关的一系列CRT中的IO函数(如_read,_write)均以下划线开头,其余与linux大致相同,其参数中所谓的文件描述符与Win32中的句柄不一样,文件描述符实际上是句柄数组的索引,也就是说文件描述符不能与句柄混用。比如0,1,2分别是标准输入、标准输出、标准错误的文件描述符,但句柄值不是这样确定的。文件描述符不是Win32的概念,是POSIX中的概念。  
  16.   
  17. _dup2用法与dup2大致相同,不多解释,不了解的可以查阅dup2相关资料。下面讲点应用。  
  18.   
  19. 二、如何应用于调试  
  20.   
  21. 写一个模块时,我们可以直接用cout/printf来作调试。但是如果这个模块用于图形界面或许是系统服务呢?这时标准输出看不到了,我们可以用 OutPutDebugString函数和DebugView这样的调试工具。这样就带来一种选择,而选择往往是增加软件复杂度的因素。所以我的想法是代码中只用cout/printf,如果需要将其重定向到调试工具中去。  
  22.   
  23. 如何实现呢,用匿名管道和线程。  
  24.   
  25. 用一个pipe,标准输出重定向到其write端,然后创建一个线程,线程要做的就是从pipe的read端读出数据后用OutPutDebugString输出。  
  26.   
  27. 下面是实现代码。  
  28.   
  29. 头文件是这样子的,构造时重定向,析构时解除:  
  30.   
  31.   
  32.  namespace common {  
  33.     // 将标准输出重定向到DebugView,保持对象存在即有效  
  34.   
  35.     class StdoutToDebugString {  
  36.     public:  
  37.         StdoutToDebugString();  
  38.           
  39.         ~StdoutToDebugString();  
  40.   
  41.     private:  
  42.         int fds_[2];  
  43.         int orign_stdout_;  
  44.         uintptr_t thread_handle_;  
  45.     };  
  46. }  
  47.   
  48. 实现文件:  
  49.   
  50.   
  51. #include <io.h>  
  52. #include <fcntl.h>  
  53. #include <stdio.h>  
  54. #include <process.h>  
  55. #include <Windows.h>  
  56. #include "StdoutRedirect.h"  
  57.   
  58. using namespace common;  
  59.   
  60. const int kBufferSize = 4096;  
  61.   
  62. unsigned __stdcall RedirectThreadProc(void* param) {  
  63.     int pipe_read = (int)param;  
  64.     char buf[kBufferSize];  
  65.     int bytes_read;  
  66.     do {  
  67.         bytes_read = ::_read(pipe_read, buf, kBufferSize);  
  68.         buf[bytes_read] = 0;  
  69.         ::OutputDebugString(buf);  
  70.     } while (bytes_read);  
  71.     return 0;  
  72. };  
  73.   
  74. StdoutToDebugString::StdoutToDebugString() {  
  75.     ::_pipe(fds_, kBufferSize, _O_TEXT);  
  76.     orign_stdout_ = ::_dup(_fileno(stdout));  
  77.     ::_dup2(fds_[1], _fileno(stdout));  
  78.     thread_handle_ = ::_beginthreadex(NULL, 0, RedirectThreadProc, (void*)fds_[0], 0, NULL);  
  79.     ::CloseHandle((HANDLE)thread_handle_);  
  80. }  
  81.   
  82. StdoutToDebugString::~StdoutToDebugString() {  
  83.     ::_dup2(orign_stdout_, _fileno(stdout));  
  84. }  
  85.   
  86. 测试代码:  
  87.   
  88.   
  89. #include <iostream>  
  90. #include <Windows.h>  
  91. #include "../Common/StdoutRedirect.h"  
  92. using namespace std;  
  93. using namespace common;  
  94.   
  95. void main() {  
  96.     StdoutToDebugStringredirect;  
  97.     cout<< "hello" << endl;  
  98.     ::system("pause");  
  99. }  
  100.    

另外一篇很不错的dup2介绍

http://www.cnblogs.com/sdphome/archive/2011/04/30/2033381.html

Qt程序调试技巧:不用改代码就能捕获std::cout输出的隐藏方法 本文针对Qt GUI应用中std::cout输出不可见的问题,提供了三种无需修改业务代码的系统级捕获方案。详细介绍了如何通过动态附加控制台、重定向至Qt Creator输出面板以及利用外部管道工具,实现非侵入式调试,尤其适合处理遗留代码或需要保持代码纯净性的项目。 阅读详情

相关推荐

VSCode插件Code Runner保姆级配置指南:解决中文乱码与终端输入难题

本文提供VSCode插件Code Runner的详细配置指南,重点解决中文乱码与终端输入问题。通过开启`Run In Terminal`选项和优化语言环境配置,帮助开发者高效运行Python、C++等代码,提升开发体验与工作效率。

weixin_30915951的博客 427

dup/dup2

dup函数的作用:复制一个现有的句柄,产生一个与“源句柄特性”完全一样的新句柄(也即生成一个新的句柄号,并关联到同一个设备) dup2函数的作用:复制一个现有的句柄到另一个句柄上,目标句柄的特性与“源句柄特性”完全一样(也即首先关闭目标句柄,与设备断连,接着从源句柄完全拷贝复制

wangwenwen的专栏 572

【信息科学与工程学】计算机科学与自动化——第二十四篇 编译器04 LLVM编译器02

B-WUCL(用户权重均匀对比损失)和D-WUCL(物品权重均匀对比损失)中,动态调整参数λ_new(新用户补偿因子)和α(长尾补偿强度)是优化推荐系统适应数据分布变化的核心。

weixin_49199313的博客 1242

C++ 流重定向输出到调试

#include #include #include #include //using namespace std; template > class basic_debugbuf : public std::basic_stringbuf { ~basic_debugbuf() { sync(); } protected: int

vingo888的专栏 1363

Windows管道(Pipe)重定向stdout,stderr,stdin

有时我们需要重定向stdout,stderr,stdin。比如:将输出写入文件,又或者我们要将命令行程序输出结果显示到Windows对话框中。源码示范如何在Windows中实现,封装了几个简单易用的函数。

UCIe物理层 —— 逻辑协议 (2)

本章开始主要介绍UCIe协议第四章,物理层逻辑定义和规范。如其他的通信协议一样,接口的物理层包含两个部分,逻辑子层和电气子层。其中逻辑层主要负责:1.定义接口信号和时序2. 定义发送端如何将上层数据分发到各个物理通道以及接收端如何把从各个通道收到的数据恢复成byte stream(Flit)。3. Broken Lane的repair和remap。4. 链路初始化,训练(training)和电源状态管理/切换。5. 扰码Scrambling和training sequence的产生。

m0_47581558的博客 1477

dup, dup2一图胜千言

一图胜千言啊,看了必须懂啊^_^ 下面这一段原文:http://os.chinaunix.net/a2009/0602/1049/000001049422_7.shtml   在C语言里,操纵文件的渠道则是FILE结构,不难想象,C语言中的FILE结构必定和fd有一对一的关系,每个FILE结构都会记录自己唯一对应的fd。   FILE、fd、打开文件表和打

Always look out for number one. 3189

PCIE协议版--M.2接口规范V1.0中文版1——物理规格篇

5.1.3.双模块键模块:同时支持Socket1-DP、Socket1-SD。2.4.7.3.3.双面模块(使用H2.8、H3.2、H4.2连接器)6.5.8.2.5.热设计功率响应-带有风扇类别的薄平台笔记本电脑。2.3.7.1. Socket1&2射频连接器PIN-OUT。5.2.2.Socket2 PIN-OUT(机械KEY B)3.2.10.1.3.极薄的笔记本电脑的电源开关顺序的例子。5.1.1.Socket1-DP(机械KEY A)5.1.2.Socket1-SD(机械KEY E)

想你所想,做你所做 4673

本进程stdout重定向到管道 以及恢复

目标 接管stdout输出,重定向到指定管道,不需要的时候则恢复。 原理 创建管道,通过微软的dup保存默认stdout,_dup2接口重定向,再通过_dup2恢复回来。 代码 参考以下代码。 int hStdOut; int hStdOutPipe[2]; if (_pipe(hStdOutPipe, OUT_BUFF_SIZE, O_BINARY | O_NOINHERIT) == -1) return -1; hStdOut = _dup(_fileno(

YT专栏 1068

ccproxy 6.61 注册机(纯绿/傻瓜/真正去除线程限制)

导读:   软件介绍   1、 CCPROXY 6.61 注册机(纯绿/傻瓜/真正去除线程限制)   ***前言,这次的升级官方改动不大,据说只是为了不被某些软件当病毒***   附件包中解压即免安装版,CcREGTOOLFF.exe为注册机。   本人继续向大家隆重推出《CCPROXY6.61哎呀……破解版》   还是那个提示:   在此之前,本人还是那句老话想提示大家,CCPROXY是

i53nd的专栏 1万+

宝骏kiwi 630 730 560 E100 E200 E300 310 510 610 330 530维修手册电路图资料线路图接线图更新

2020-2022年宝骏RS-3维修手册和电路图。2020-2022年宝骏RS-3维修手册和电路图。2019-2021年宝骏RC-6维修手册和电路图。2019-2021年宝骏RC-6维修手册和电路图。2019-2020年宝骏RS-5维修手册和电路图。2019-2020年宝骏RS-5维修手册和电路图。2019-2020年宝骏RM-5维修手册和电路图。2019-2020年宝骏RM-5维修手册和电路图。2019-2021年宝骏510维修手册和电路图。2019-2021年宝骏510维修手册和电路图。

weixin_45821055的博客 1770

windows下重定向命令

1. > > 或者 1> 是正确信息重定向 输出正确的信息到目标文件,错误信息还是会输出到控制台 上例中,1.txt文本会自动创建,但是不会记录信息(因为没有正确信息,只有报错信息) 2> 是错误信息重定向 可以两者一起使用,将错误信息和正确信息分开记录 cmd 1>suc.txt 2>fail.txt 也可以将两者输入到同一个文件中...

Mr_moving 5472

uniApp微信小程序:error: 60001 request:fail errcode:-101 cronet error code:-101error_msg:net::ERR CONNECTI

uni-app微信小程序域名访问报error 60001 request:fail errcode:-101,解决Uniapp微信小程序报600001错误,uni.request()接口请求报错,服务器更换SSL证书后,uniapp微信小程序出现`request:fail errcode:-101`问题分析与解决,服务器更换ssl证书后,手机访问微信小程序异常,微信小程序更换SSL证书后出现请求报错,服务器更换SSL证书,微信小程序报600001,小程序反应偶尔出现request:fail errcode:

✅ 精选推荐文章 4580

强制打印方法,输出重定向解决

在平常调试程序时候,经常发现标准输出被重定向了,也就是说printf无法打印,以下提供三种方法强制打印。 方法一: #include <syslog.h> #include <sys/syslog.h> #include <stdarg.h> #include <stddef.h> #include <stdio.h> #include <unistd.h> static int doser_debug_print_messa

zz2633105的博客 1343

【QT开发教程】QMatrix4x4类详解及实战应用:Qt中的4x4矩阵变换

在计算机图形学和三维图形应用中,矩阵变换是一个核心概念。Qt框架提供了QMatrix4x4类,用于处理4x4矩阵变换,帮助开发者在三维空间中进行复杂的几何计算。本文将深入探讨QMatrix4x4的功能及其在Qt应用中的实际应用。

科技改变人类,技术成就未来 715

BME688传感器原理图设计,已量产(环境传感器)

在便携式空气质量监测、可穿戴健康设备这类低功耗场景中,BME688 这类集成了 VOC、温湿度、气压的四合一 MEMS 传感器越来越受欢迎 —— 它体积小、功耗低,刚好匹配便携设备的需求。但这类小信号传感器对电源噪声、电平匹配的要求很细,今天结合实际项目里的一款 BME688 接口电路,聊聊硬件设计的关键细节。

不脱发的程序猿 513

windows的键盘输入重定向

在POJ, vijos上刷题目时,如果遇到要输入数据的问题,还是有点点麻烦的。因为这些网站上的题目都是标准输入和输出。如果真要一个一个输入,当然有点笨,至少可以在控制台中用复制黏贴命令,但还是有点点不方便。其实这些网站用标准输入和输出还是有其考虑的,因为windows和Unix都支持输入输出重定向。不一定要在控制台中输入,仍然可以从文件读取数据,当然也可以写到控制台的内容,重定向到文件。很简单pro

WhoisPo的专栏 2238

【FISCO BCOS】二十、多机部署区块链

实际开发中,为了满足高可用性和高容错性的需求,往往会采用多级部署区块链的方式,今天介绍一下FISCO BCOS的多机部署流程。

naihe_fish的博客 3645

输出重定向 标准信息数字

1>/dev/null 2>&1 下面解析一下上面的那个语句 >前面的数字: 0代表标准输入 1代表stdout标准输出,默认值为1,所以”1>/dev/null”可以简写为”>/dev/null” 2代表stderr标准错误输出 2>&1代表把stderr标准错误输出 重定向 到1表示的stdout标准输出所在的地方,也就是 /dev/null 注意2>1这里的1表示的是文件

xxx 382

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

freopen重定向stdin与stdout后如何恢复正常

函数定义如下: FILE * freopen ( const char * filename, const char * mode, FILE * stream ); 在windows下控制台的标准输出设备是CON,在linux下面则用/dev/tty来显示当前终端,标准的应该是/dev/console,但个人试验只有tty的情况下 才能成功。设置了set-user-id并将user 改

韩小侠的专栏 已迁移至lssea.com 8605

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

QT Creator控制台程序调试:为什么你的黑窗口总弹出来?一个配置项就搞定

本文深入解析了QT Creator调试控制台程序时黑窗口弹出的原因,并提供了一个关键配置项解决方案。通过分析Windows系统的控制台宿主进程机制,详细说明了如何通过修改QT项目文件(.pro)中的`CONFIG`选项来避免黑窗口弹出,同时提供了跨平台调试技巧和最佳工程实践配置。

weixin_31115195的博客 281

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

国际象棋引擎文章(二)匿名管道操作

     管道(Pipe)实际是用于进程间通信的一段共享内存,创建管道的进程称为管道服务器,连接到一个管道的进程为管道客户机。一个进程在向管道写入数据后,另一进程就可以从管道的另一端将其读取出来。匿名管道(Anonymous Pipes)是在父进程和子进程间单向传输数据的一种未命名的管道,只能在本地计算机中使用,而不可用于网络间的通信。        匿名管道由CreatePipe()函数创建

xiaoGang的专栏 1686

云原生技术问题

整体流程涉及DNS、ARP、TCP、IP、HTTP核心协议,完整过程如下:首先进行DNS解析,将域名解析为服务器IP,依次查询浏览器缓存、系统hosts、本地DNS缓存,未命中则向DNS服务器迭代查询。核心区别:TCP是面向连接的可靠传输协议,需三次握手建连,具备重传、校验、流量控制、拥塞控制机制,报文开销大、传输延迟高;traceroute利用ICMP超时报文:通过逐级递增数据包TTL值,每经过一台路由器TTL减1,TTL归零后路由器返回ICMP超时报文,以此获取链路所有路由节点IP,定位故障链路。

2303_81849819的博客 464

dup和dup2函数

【代码】dup和dup2函数。

优快云_DU666666的博客 423

控制台进程重定向(Win32, C++)

简单控制台输入输出重定向

FlameCyclone的博客 531
上一篇: Sizeof与Strlen的区别与联系
下一篇: 了解 Boost 单元测试框架
nodeathphoenix
博客等级 码龄16年 97粉丝 99原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值