【问题标题】:Windows UAC is messing with file buffersWindows UAC 弄乱了文件缓冲区
【发布时间】:2012-09-23 21:49:08
【问题描述】:

对于这个问题中缺少代码 sn-ps 及其模糊性,我请求您耐心等待,但我完全一无所知,我对错误的位置没有任何线索,我无法粘贴整个应用程序。

我有一个跨平台应用程序,它通过普通的C API(fopen 等)打开一个文件,写入一些数据(首先将缓冲区传递给 zlib 以使其放气,但我不认为这是相关)持续一段时间,最后刷新并关闭它。

这在所有平台上都可以正常工作,除了在 Windows OS x64 上打开 UAC 的 64 位版本。基本上,在那个精确的设置中,在我打开文件和刷新它之间,文件缓冲区似乎与我发送到stdout 的内容交错,好像对stdout 的任何写入都使用了相同的缓冲区另一个文件。

重要的是要注意,这不应该与任何文件系统虚拟化(VirtualStore 机制)相关,正如我在%USERPROFILE%\Saved Games\ 中所写的那样。这个问题肯定与 UAC 有关,因为如果我关闭它,问题就不会发生。 wine64 也没有问题。

任何指针都是有价值的。编译器是g++ 4.7.0(从linux交叉编译)。

【问题讨论】:

  • 你能发布一些示例代码吗?
  • 当我说我不知道​​错误的位置,所以粘贴一些相关代码意味着粘贴整个应用程序时,我是认真的。
  • 建议:你能用一个小的、独立的测试用例重现这个问题吗(例如:“printf (some-text)/fopen (some-file-in-%userprofile%-saved-games)/fprintf (some-different-text)/fclose()”?问:“从 Linux 交叉编译 gcc 4.7.0”是什么意思?问:您是否尝试过直接在 Windows 上编译(例如使用 MSVC?)
  • 使用 sysinternals 的进程监视器来仔细查看真正写入的内容和位置
  • 在这种情况下有时会有所帮助的一种方法是复制您的源代码,然后开始批量提取零件(根据需要用虚拟代码替换它们)直到出现 (a) 问题消失了,在这种情况下,您可以查看最近删除的代码以寻找线索;或 (b) 您有一个可以发布的独立测试用例。这可能是一项艰巨的工作,因此它是最后的手段,但如果调试没有为您提供所需的线索,它可能是您唯一的选择。

标签: windows uac windows64


【解决方案1】:

我找到了解决此问题的方法。

第一个障碍是我使用-mwindows 编译了我的应用程序,这阻止了我的应用程序附加到父进程控制台。但是切换到-mconsole 并不仅仅是解决它。即使有了这个更改,我发送到stdout 的所有内容都没有发送到控制台。我没有在问题中说明这个问题,因为这没什么大不了的,应用程序中有另一种控制台。

我确信整个问题是由于msvcrt 中的一些错误(或一些记录非常差的行为更改)造成的。基本上,当我的应用程序启动时,stdout 是一个有效的指针,但它并没有真正附加到父控制台。我必须做一个freopen( "CON", "wt", stdout ); 才能看到输出。此外,fileno(stdout) 没有 UAC 正确返回 1,但是打开 UAC,stdout 仍然是一个有效的指针,但对 fileno(stdout) 的调用返回 -1!我想知道在第二种情况下真正的stdout 指向哪里。

有趣的是,当使用-mwindows 编译时,fileno(stdout) 返回 3!我不知道 POSIX 标准是否要求 stdout 的文件描述符编号为 1,但至少选择 3 是不寻常的。

【讨论】:

  • 使用 -mwindows 编译指示链接器构建 GUI 应用程序。 Windows 不提供具有标准输入/输出流的 GUI 应用程序,因此在这种情况下,stdout 不是一个打开的文件,并且 fileno 的结果未定义根据 msdn.microsoft.com/en-us/library/aa246862%28v=vs.60%29.aspx
  • 应用程序是否请求 UAC 提升?这可以解释不同的行为;如果启用了 UAC,则会发生 UAC 提升,并且 UAC(不是控制台)是父进程。另一方面,如果您使用 -mconsole 编译,我希望在这种情况下创建一个新控制台。
  • 第三方面,由于 Visual Studio 6 没有构建 AMD64 应用程序,64 位版本的 msvcrt.dll 没有记录,所以很可能是故意的行为改变。另请注意,POSIX 标准不适用,因为 msvcrt 不会尝试提供 POSIX 兼容性。
  • @HarryJohnston 它不需要任何 UAC 提升。还有一个怪癖:我猜“freopen”混淆了“consolehost”,因为它在我的应用程序退出后崩溃,即使是32位构建。无论如何感谢您的澄清,我并没有真正意识到我在未定义的土地上。
  • 哦,又是一个怪癖。如果我不通过 .bat 文件(打开控制台)打开我的应用程序,而是创建一个直接快捷方式,那么是的,我的应用程序会自行打开一个控制台,但它不显示任何输出。我真的很困惑。
猜你喜欢
  • 2011-03-05
  • 1970-01-01
  • 2014-07-20
  • 1970-01-01
  • 2020-01-16
  • 1970-01-01
  • 1970-01-01
  • 2023-03-14
  • 1970-01-01
相关资源
最近更新 更多