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

CEF crashes when calling functions in a particular DLL

本文关键字:CEF 崩溃 函数 调用 DLL      更新时间:2023-10-16

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

  1. 所有的调用都是从可执行文件完成的。
  2. 我调用cefDLL中的函数来初始化CEF。
  3. 我调用第二个通用dll函数。
  4. CEF内部的一些线程崩溃并弹出Windows错误报告"应用程序无法正确启动(0xc0000124)"。点击OK关闭应用程序。
  5. 出现Windows弹出窗口声明Application.exe已停止工作。
  6. 主线程继续运行,即使我关闭程序在"已停止工作"的弹出。

如果我尝试在崩溃的程序上运行调试器,我得到一个空白的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);

有人知道这可能是由什么引起的吗?这是我遇到过的最奇怪的bug之一。这个项目有5万行左右,而且没有其他相关的部分,所以我恐怕不能提供任何例子。请告诉我,如果有一些代码,你认为这将有助于看到虽然。

您知道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使用派生的App,在那里你可以重写任何你需要的处理程序。您可能希望从simple_app示例开始进行非常基本的覆盖。

对于调试问题,尝试附加到所有启动的进程,假设我错了,多个进程都正确启动。