调用特定 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 崩溃的主要内容,如果未能解决你的问题,请参考以下文章