从静态库构建的 DLL 正在刷新控制台

问题描述 投票:0回答:1

这是我遇到的一个麻烦,并为此奋斗了几天。

  1. 我们有一个软件工件,我们将其作为 DLL 和静态库进行分发;
  2. 一个客户想要使用该静态库与多个其他静态库一起构建这个巨大的DLL(业务需求:只有一个DLL文件);
  3. 他实际上可以构建并链接巨大的 DLL,但是当他以某种方式加载它时(使用 VB6 或 Delphi 或 C#),它会在加载过程中闪烁控制台窗口;
  4. 客户不喜欢这个控制台闪烁(我也不喜欢),我已经尝试了多种解决方案:添加 生成 DLL 时将
    -Wl,--subsystem,windows
    -mwindows
    添加到链接器行(重要信息:DLL 是使用 MSYS2 上的 GCC 工具链构建的),搜索可能具有显示控制台副作用的 Windows API,尝试删除一些出于同样的原因依赖;
  5. 如果客户端直接使用我们的 DLL(与许多其他 DLL),则一切正常(没有控制台闪烁)。我们的两个库(DLL 和静态)都是从相同的代码库构建的;
  6. 我还尝试删除部分代码,并得出结论:实际上是我自己的代码导致控制台闪烁。我只是不知道在哪里。该 DLL 是用 C 和 C++ 混合编写的,使用模板和一些 Windows API;
  7. 作为最后一次尝试,我搜索了一些可能实际调用
    AllocConsole
    API 的库,但什么也没找到;
  8. 这个库实际上是许多知名库的更高级别的包装:zlib、libpng、cairo、freetype 等。我想知道这些库中是否有任何一个可能是这里的罪魁祸首,但我也想知道为什么在 DLL 构建中它会这样做不出现。

有人可以给我一些指示吗?

谢谢!

c dll mingw static-libraries
1个回答
0
投票

`“我刚刚了解到代码中的几个地方有许多 fprintf(stderr, 调用。您认为这些可能是罪魁祸首吗?”'

答案:有可能。这里有一些“短期修复”代码可以帮助您找到答案。在程序入口/开始附近的某个位置添加此代码以关闭

stderr
(以及可选的
stdout
)。

这里是一些可运行的代码,因此您可以看到它在关闭

stderr
(和
stdout
)的输出方面有多有效。 我想强调的是,这是短期的;只是为了发现阶段,看看是否有帮助。

关闭

stdout
stderr
然后向它们写入可能会导致
undefined behavior
(!):

#include <stdio.h>

int main()
{
    fprintf(stdout, "Text for output to stdout\n");
    fprintf(stderr, "Text for output to stderr\n");

    /* Short- term fix: close stderr (and optionally stdout) */
    fclose(stdout);
    fclose(stderr);

    fprintf(stdout, "Text to stdout cannot display!\n");
    fprintf(stderr, "Text to stderr cannot display!\n");

    return 0;
}

即使上面的代码不能解决问题,更强大、更长期、更安全的解决方案将是类似以下内容。在此解决方案中,我们使用

FILE
指针
error_logfile
打开日志文件。然后我们将所有“
fprintf(stderr
”实例替换为“
fprintf(error_logfile
”。这种替换可以通过像
Notepad++
或类似的东西这样有能力的编辑器一步完成。

这更好,因为它是标准 C。如上所述,我们之前的

solution
关闭了
stderr
,但允许对其进行写入,这可能会导致
undefined behavior

此外,这保留了(至少现在)原始代码的意图,即捕获错误消息。 FWIW,这些天我大约 50% 的代码都在做这种错误记录。它并不优于调试会话,但它可以无限期地保留在代码中,甚至可以有效地揭示生产中的问题,取决于您的客户/客户

#include <stdio.h>

int main()
{
    /* Long-term fix:
    * 1.) Add this code block to the code */
    FILE *error_logfile = fopen( "error.log", "w+" );
    if( error_logfile == NULL )
    {
        printf("The debug logging file could not be opened.\n");
        return 0;
    }
    /* 2.) Replace all instances of "fprintf(stderr" with "fprintf(error_logfile" */
    fprintf(error_logfile, "Text for output to Error Log File.\n");
    return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.