C/C++ 开发的经常会用printf cout 输出一些调试信息,如果将程序前台启动就会输出到控制台,自己写的代码还好,可以删掉,但有的时候用别人的库或者代码,带有大量的printf,程序一启动就会刷屏,就不能操控程序或者看不到自己想看的信息。这个适合可以用dup/dup2 复制一下标准输出,然后在关掉标准输出。
但最近调试程序的时候突然发现,关掉标注输出后,原本printf 输出的内容出现在了我的日志文件里,导致我的日志文件极速增长,并且很难看到原本我的日志输出,突然不知所以,觉得这个方法不香了,苦恼了好一会儿。艰难的调完程序后静下心来想这个事儿。应该是close(1)后,我日志文件的fd 刚好是1,导致问题的出现。因为close(1) 后fd 1 被回收,刚好日志文件是第一个打开的文件,恰恰使用了1。下面通过代码验证了这一猜测。
先看一下有问题的代码
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
int fdout,fderr,fdlog;
int my_print (const char *__restrict __format, ...){
char tmpstr[2048] = {0};
va_list args;
va_start(args,__format);
int ret=vsnprintf(tmpstr,sizeof(tmpstr),__format,args);
va_end(args);
ret = write(fdout,tmpstr,strlen(tmpstr));
return ret;
}
int my_log (const char *__restrict __format, ...){
char tmpstr[2048] = {0};
va_list args;
va_start(args,__format);
int ret=vsnprintf(tmpstr,sizeof(tmpstr),__format,args);
va_end(args);
ret = write(fdlog,tmpstr,strlen(tmpstr));
return ret;
}
int main(int argc, char* argv[])
{
fdout = dup(1);
fderr = dup(2);
dup2(1,fdout);
dup2(2,fderr);
close(1);
close(2);
fdlog = open("./mylog",O_CREAT|O_RDWR|O_APPEND);
my_log("my_log out ..\n");
printf("std printf out ...\n");
my_print("my_print out ... \n");
return 0;
}
查看程序输出
先复制1然后,close(1)后,my_print输出到了控制台,printf的输出不会再输出到控制台,但却出现在我打开的日志文件里。
用gdb 看一下fdlog的值
fdlog 的值确实是1。
下面对代码进行修改,打开null文件占用1和2
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
int fdout,fderr,fdlog;
int my_print (const char *__restrict __format, ...){
char tmpstr[2048] = {0};
va_list args;
va_start(args,__format);
int ret=vsnprintf(tmpstr,sizeof(tmpstr),__format,args);
va_end(args);
ret = write(fdout,tmpstr,strlen(tmpstr));
return ret;
}
int my_log (const char *__restrict __format, ...){
char tmpstr[2048] = {0};
va_list args;
va_start(args,__format);
int ret=vsnprintf(tmpstr,sizeof(tmpstr),__format,args);
va_end(args);
ret = write(fdlog,tmpstr,strlen(tmpstr));
return ret;
}
int main(int argc, char* argv[])
{
fdout = dup(1);
fderr = dup(2);
dup2(1,fdout);
dup2(2,fderr);
close(1);
close(2);
int fd_tmp1 = 0,fd_tmp2 = 0;
// 打开null文件占用1和2
fd_tmp1 = open("/dev/null",O_WRONLY);
fd_tmp2 = open("/dev/null",O_WRONLY);
fdlog = open("./mylog",O_CREAT|O_RDWR|O_APPEND);
my_log("my_log out ..\n");
printf("std printf out ...\n");
my_print("my_print out ... \n");
my_print("fd_tmp1 = %d,fd_tmp2 = %d\n",fd_tmp1,fd_tmp2);
return 0;
}
这样既能用my_print输出到控制台,原来的printf也不会影响日志文件。