黄铎彦 2023-03-18 18:04 采纳率: 0%
浏览 120
已结题

用freopen把标准输出重定向到文件再重定向回来,之后为什么无法获取 CONSOLE_SCREEN_BUFFER_INFO ?

我听了GPT的话,想少写几行代码,于是这样操作:

#include <stdio.h>
#include <Windows.h>

/// <summary>重定向标准输出流到某个文件</summary>
/// <param name="filename">
/// 文件名。如果原来的文件存在,则覆盖它;否则新建一个文件。
/// <para>如果想要将标准输出重定向到控制台,请再次使用此宏,文件名填 "con",
/// 即 Windows 的控制台文件。</para>
/// </param>
#define REDIR_STDOUT(filename) assert(freopen(filename, "w", stdout) != NULL)

// ...
        case 4: // 保存链表的数据到文件。
        {
            REDIR_STDOUT(FILENAME);
            pri_dates(&l);
            REDIR_STDOUT("con");
        }
            break;

// ...
        HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE); // 输出句柄
        CONSOLE_SCREEN_BUFFER_INFO csbi;
        assert(GetConsoleScreenBufferInfo(hout, &csbi)); // 断言失败,返回ERROR_ACCESS_DENIED!

pri_dates(&l); 中,l 是链表,这个调用的意思是在屏幕上打印日期链表的内容。用"con"重定向回控制台的时候还是可以在屏幕上输出内容的。后面的 Win32 API 调用部分是因为功能需要增加的。如果没有重定向的话 csbi 的信息可以正常获取,断言成功。不知道为什么无法获取 csbi 的信息,难道是 hout 获取到了非法的句柄了吗?

  • 写回答

6条回答 默认 最新

  • lshen01 2023-03-18 18:15
    关注

    参考GPT和自己的思路:

    根据你的描述,使用 freopen 在应用程序运行时将标准输出流重定向到文件,然后再将其重定向回控制台。然而,在还原标准输出之后,无法成功调用 GetConsoleScreenBufferInfo 函数获取控制台屏幕缓冲区信息。我们来看看可能的原因:

    可能原因一:文件句柄没有正确关闭

    在调用 REDIR\_STDOUT("con") 之前,你需要确保先关闭之前打开的文件句柄。否则,系统可能无法正确释放资源,导致后续系统调用出错。你可以添加 fclose(stdout) 或 _fcloseall() (关闭所有打开的文件)来关闭文件句柄。

    可能原因二:GetStdHandle 函数获取的句柄值不正确

    另外一个原因是,你在重新打开控制台后,GetStdHandle 获取到的控制台输出句柄可能不再是先前的句柄。这可能是由于 freopen 调用期间系统在内部重新分配句柄。如果此情况发生,可以尝试使用 GetStdHandle(STD_ERROR_HANDLE) 或 GetStdHandle(STD_INPUT_HANDLE) 获取其他句柄来获取控制台信息。如果这些方法也失败了,可能需要关闭应用程序并再次启动。

    总之,建议在页面顶部添加 #include <stdlib.h> 和 #include <assert.h> 头文件,这样可以在需要时使用 exit 函数增强程序鲁棒性,使用 assert 断言来检查系统调用是否成功执行。

    评论

报告相同问题?

问题事件

  • 系统已结题 3月26日
  • 修改了问题 3月18日
  • 修改了问题 3月18日
  • 修改了问题 3月18日
  • 展开全部