调用特定 DLL 中的函数时 CEF 崩溃

Posted

技术标签:

【中文标题】调用特定 DLL 中的函数时 CEF 崩溃【英文标题】:CEF crashes when calling functions in a particular DLL 【发布时间】:2015-07-23 04:37:47 【问题描述】:

我有一个 MSVC 项目,该项目由多个从可执行文件调用的 DLL 组成。其中一个 DLL 初始化 CEF(Chromium Embedded Framework),另一个提供一些其他通用功能,我们将它们称为 cefDLL 和 generalDLL。电话是这样的:

    所有调用都是从可执行文件中完成的。 我调用 cefDLL 中的函数来初始化 CEF。 我将函数称为第二个通用DLL。 CEF 中的某些线程内部崩溃并出现 Windows 错误弹出窗口报告“应用程序无法正确启动 (0xc0000124)。单击确定关闭应用程序。”。 出现一个 Windows 弹出窗口,声明 Application.exe 已停止工作。 即使我在“已停止工作”弹出窗口中关闭程序,主线程也会继续运行。

如果我尝试在崩溃的程序上运行调试器,我会得到一个空白的 Visual Studio,没有调用堆栈,没有本地变量,什么都没有,甚至没有失败的 DLL 的名称。

如果我从另一个 DLL 调用一个函数,或者从可执行文件本身调用一个函数,或者根本不调用一个函数,代码就可以很好地到达我的无限循环(我正在使用无限循环来阻止程序的其余部分运行)。

如果我让它继续运行到程序的其余部分并且不使用无限循环停止它,CEF 中的另外两个线程崩溃,总共三个崩溃线程。这些产生与第一个线程完全相同的错误。我不确定是什么原因造成的,因为我还没有时间研究这个问题。

即使在一般DLL 中调用的函数完全不执行任何操作,这仍然会发生。如果我的代码是

,我确定是调用它们的行为导致了这种情况
initializeCEF();

while (true)



如果代码是,它可以工作

initializeCEF();

someBlankFunctionInGeneralDLL();

while (true)



线程崩溃。

CEF 的初始化包括:

//Initialize
CefMainArgs mainArgs;

//Launch Threads
CefExecuteProcess(mainArgs, nullptr, nullptr);

//Settings
CefSettings settings;
settings.pack_loading_disabled = true;
settings.windowless_rendering_enabled = true;
settings.multi_threaded_message_loop = false;
settings.no_sandbox = true;

//Sandbox Info
void *sandboxInfo = nullptr;

//Launch System
CefInitialize(mainArgs, settings, nullptr, sandboxInfo);

有没有人知道这可能是由什么引起的?这很容易成为我遇到过的最奇怪的错误之一。 这个项目非常庞大,大约有 50,000 行,而且实际上没有任何其他相关部分,所以恐怕我无法提供任何示例。让我知道是否有一些您认为有助于查看的代码。

【问题讨论】:

【参考方案1】:

您知道 CEF 是多进程的,对吧?正在初始化 CEF 的主应用程序是否有可能无法正确启动多个实例,或者在启动时没有将所需的命令行参数传递给包含 CEF 的 DLL?有关 CEF 应用程序的结构,请参阅此文档:https://bitbucket.org/chromiumembedded/cef/wiki/Architecture#markdown-header-cef3

您可以尝试使用“--single-process”参数启动 CEF,以强制它运行单个进程(尽管非常不推荐使用此选项,因为他们不会在此配置中测试 Chromium - 它只是为了调试)。如果您没有将命令行参数传递给 CEF,那可能是您问题的开始。为此,您可以在 CefApp 派生类中为 OnBeforeCommandLineProcessing() 添加一个处理程序,正如 CEF 的创建者在此处推荐的那样:http://www.magpcss.org/ceforum/viewtopic.php?f=6&t=12928&p=25732&hilit=main_args#p25717。覆盖最终看起来像这样:

void ServiceCenterApp::OnBeforeCommandLineProcessing(const CefString& process_type,
                                                 CefRefPtr<CefCommandLine> command_line) 

if(!command_line->HasSwitch("single-process")) 
    command_line->AppendSwitch("single-process");

但我没有看到您定义 CefApp 派生类,这将是 CefInitialize() 的参数。例如,cefclient 示例的 wWinMain() 中有这个:

 // SimpleApp implements application-level callbacks. It will create the first
  // browser instance in OnContextInitialized() after CEF has initialized.
  CefRefPtr<SimpleApp> app(new SimpleApp);

紧随其后

  // Initialize CEF.
  CefInitialize(main_args, settings, app.get(), sandbox_info);

您告诉 CEF 使用派生应用程序的位置,您将覆盖您需要的任何处理程序的位置。您可能希望从 simple_app 示例开始进行非常基本的覆盖。

对于调试问题,尝试附加到所有启动的进程,假设我不正确并且多个进程正在正确启动。

【讨论】:

多进程和多线程有区别吗?我也想传递命令行参数,但我不知道如何模拟它们,如何将参数添加到 CefMainArgs 对象? 这里的 CEF 文档magpcss.org/ceforum/apidocs3/projects/(default)/… 描述了一个构造函数,它接受参数 argc 和 argv 这基本上是我想要的,但由于某种原因,我拥有的版本 (3.2) 中缺少它... 是的,CEF 既是多进程又是高度多线程的。有关架构的信息,请参阅bitbucket.org/chromiumembedded/cef/wiki/…。我们基于 CEF 的产品会自动生成渲染器(对应于浏览器选项卡)和 gpu 子进程。另见bitbucket.org/chromiumembedded/cef/wiki/… 关于 main_args,如果你看这个:bitbucket.org/chromiumembedded/cef/wiki/… 它提到在 Windows 上他们通过 hInstance 获取命令行,只有在 Mac 和 Linux 上你才显式传递命令行。这是 CEF 的创建者对如何将命令行参数强制为 main_args 的评论。我正在用更多信息更新我的答案。 供参考 CefExecuteProcess 实际上会为您执行 --type 命令行参数检查。如果找不到--type,它将返回-1,因此无需手动解析。典型使用场景类似bitbucket.org/chromiumembedded/cef/src/…

以上是关于调用特定 DLL 中的函数时 CEF 崩溃的主要内容,如果未能解决你的问题,请参考以下文章

使用 DLLImport 函数时程序崩溃

缺少 dll 功能检测

调用OpenGL函数时程序崩溃

如何在dll注入中调用特定函数?

异步回调函数

从 C# 模块调用 C++ 函数会引发随机崩溃