【问题标题】:cout and printf Works On Dll Built In Debug Not Releasecout 和 printf 工作在 Dll 内置调试​​未发布
【发布时间】:2012-12-21 22:15:10
【问题描述】:

我已经构建了一个 DLL,它通常通过 SetWindowHookEx 注入到控制台应用程序中。 DLL 将信息输出到我一直在使用 std::cout 的控制台很重要。 DLL 接近完成,直到我尝试在发布模式下构建 DLL,这使得所有 cout 行都无用。我已经验证了 DLL 正在注入并通过执行简单的 null 取消引用来执行,这会导致程序在 dllmain 函数中崩溃。与 std::printf 相同。

void onAttach()
{
    //WARNING THIS IS A DEMONSTRATION
    std::cout<<"test"<<std::endl;
    //int* intPtr = 0;
    //*intPtr = 3; //This causes a crash
}

// entry point
BOOL WINAPI DllMain ( HMODULE hModule, DWORD dwReason, LPVOID lpReserved )
{
    switch ( dwReason )
    {
        case DLL_PROCESS_ATTACH:
            DisableThreadLibraryCalls ( hModule );
            CreateThread ( NULL, 0, ( LPTHREAD_START_ROUTINE ) onAttach, NULL, 0, NULL );
            return true;
        break;

        case DLL_PROCESS_DETACH:
            return true;
        break;
    }
}

我真的不知道如何解决这个问题。 Release 链接器是否以某种方式排除了依赖项?

我正在使用 MSVS 2010 和默认发布/调试配置设置。 debug dll大约5137kb,release dll只有23kb。

【问题讨论】:

  • 我怀疑stdout 在调试中被刷新,但不是在发布中。在发布时尝试std::cout &lt;&lt; "Test" &lt;&lt; std::endl;
  • 不幸的是,与 cout 使用 endl 的情况相同。
  • printf 调用不会刷新输出。它还使用与 std::cout 不同的缓冲区,因此您真的不应该混合使用这些缓冲区。
  • 您是否链接到 C 运行时的 DLL 版本 (/MD)?如果您使用WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), "test", 4, NULL, NULL) 而不是使用printfcout,您可以打印到控制台吗?
  • @AdamRosenfield 啊,谢谢。 WriteFile 有效。关于为什么会这样的任何理论?我试过调用 std::cout.flush() 虽然换行符应该这样做。

标签: c++ visual-studio-2010 dll dll-injection


【解决方案1】:

你不应该在依赖于另一个 DLL 的 DllMain 中做任何事情。您至少违反了 3 次:printfstd::cout 依赖于 CRT(这又依赖于 Win32 DLL),CreateThread 依赖于 Kernel32.DLL。

DllMain 用于简单的事情,例如将变量归零等。

【讨论】:

  • sigh 这只是一些基本的代码来说明问题。请发挥你的想象力,假装它在 onAttach 函数中,你会吗?更不用说这至少不能回答这个问题。我感谢所有答案,但这似乎更像是一个刺拳而不是一个答案。
  • @Slight:DllMain 中代码的行为非常不可预测,并且严重依赖于 DLL 加载顺序。由于调试构建将依赖于不同的 DLL(例如 ToolHelp.DLL),因此几乎可以确定 DLL 加载顺序不同。因此,仅在 DllMain 中有这样的代码就足以解释观察到的行为。而且我显然无法根据您没有向我们展示的代码提供答案。
  • @salters 我的代码正在被注入。从此以后,您可以假设我的 DLL 是最后加载的。我还提到我在整个项目中都使用了 std::cout 。您的帖子更像是“建议”,而不是您在最后一句话中承认的答案。
【解决方案2】:

我知道@salters 说不应该在 DLL 中调用其他库是正确的,但经过反复试验,我发现在 x64 配置(而不是 x86)中编译 DLL 时,DLL 可以“cout " 或显示使用 "MessageBox" 函数没有任何问题(可能会调用许多其他库的函数)。希望这会有所帮助:)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-04
    • 1970-01-01
    • 2011-06-26
    • 2011-04-27
    • 2010-12-10
    相关资源
    最近更新 更多