2

在使用启用了 VCL 样式的简单 TOpenDialog 时,我遇到了崩溃/异常。

如果没有启用样式,对话框当然可以正常工作。C++ Builder 10 和 10.1 Professional 会出现此问题。

重现:

  1. 创建一个使用样式的简单 VCL 表单
  2. 在窗体中添加一个 TComboBox、一个 TButton 和一个 TOpenDialog
  3. 将以下代码添加到按钮的 OnClick 事件中

    OpenDialog1->Execute();
    for(int i=0; i<100; i++)
      ComboBox1->Items->Add("test text");
    ComboBox1->ItemIndex = 1;
    
  4. 运行应用程序,单击按钮并选择一个文件

  5. 对我来说,这会产生一个异常“系统资源不足”

此错误可以在 Windows 7 Enterprise 和 Windows 8.1 Pro 上重现。TSaveDialog 有同样的问题。

对我来说奇怪的是,关于这个例外,我在网上找不到类似的问题。在我看来,只需要 VCL 样式和 TOpenDialog 就可以了,我希望在网络上有更多关于这个的信息。

我只发现了一些远程相似的东西,但那里没有例外,也没有关于原生 VCL 样式的解决方案:

在 TOpenDialog 中右键单击文件时使用自定义样式显示无效字符

我还尝试禁用 SystemHooks shDialogs(请参阅屏幕截图),我在某处读到有关 VCL 样式的另一个问题,但无济于事。

代码

例外


* 编辑 2016/05/26 *

Remy Lebeau 要求获得 MCVE。我试图将所有内容都放在问题中,但为了清楚起见,这里有一个 MCVE 的摘要:

  • 使用默认设置创建新的 VCL 项目
  • 将 TComboBox、TButton 和 TOpenDialog 拖放到表单中
  • 将以下代码添加到按钮的 OnClick 事件中:

    void __fastcall TForm1::Button1Click(TObject *Sender) 
    {
      OpenDialog1->Execute();
      for (int i=0; i<100; i++)
        ComboBox1->Items->Add(L"test text");
      ComboBox1->ItemIndex = 1;   // <- exception occurs here
    }
    
  • 在项目选项中启用 VCL 样式“Smokey Quartz Kamri”

  • 运行程序,按下按钮,选择任何文件并在 TOpenDialog 中选择 OK

在这里,这就是异常所需的全部内容。

在我看来,对 Execute() 的调用会弄乱一些 VCL 结构(仅在启用样式的情况下),然后访问另一个 VCL 项(在我的情况下为组合框)会导致崩溃。

我现在知道不是每个人都有这个崩溃。因此,如果这不是对你们每个人都 100% 可验证的示例,请原谅我。

但是我和我的同事不可能是唯一发生此崩溃的人(现在在具有 3 个不同操作系统版本的 4 台不同计算机上进行了测试),可以吗?

* 编辑 2016/05/27 *

关于 Tom Brunberg 的单步请求,异常发生在 WndProc 中的某处,在调用中地址 005459F4 的屏幕截图中。

如果我更进一步,我将登陆 TCustomCombo.WndProc 中的某个位置。由于 WndProc 中的重复循环,之后很难进一步跟踪,似乎无法到达异常触发的最终位置。

在此处输入图像描述

* 编辑 2016/05/27 秒 *

好的,我设法查明了坠机的确切位置。在VCL.Graphics 内的函数CopyBitmap 中。在第一个屏幕截图中,异常发生在以下行:

结果 := GDICheck(CreateCompatibleBitmap(ScreenDC, bmWidth, bmHeight))

在第二个屏幕截图中的函数 GDICheck() 中,变量 Value 在调试器中为零,因此又调用了函数 GDIError。在那里,ErrorCode 也为零,这导致调用 OutOfResources。

希望这有助于进一步缩小范围。

在此处输入图像描述

在此处输入图像描述


* 编辑 2016/07/19 *

由于这里似乎没有人有这个问题,我们给了它一个不同的尝试:我公司的一位同事用英语安装了新的 C++ Builder 10.1 Berlin(我认为可能是德国的 IDE 是罪魁祸首),然后第一件事就是安装,重新创建 StylesCrashTest 应用程序。结果是一样的,它在选择一个文件并在对话框中点击“打开”后立即崩溃。 在此处输入图像描述

我已经在这里上传了测试项目 http://fboom.me/file/9904e22ddd22b/StylesCrashTest.zip

和我们在这里生成的发布 exe http://fboom.me/file/368d0b62cc1a7/StylesCrashTest.exe

该 exe 已通过 virustotal.com 上的许多防病毒扫描程序进行测试。 https://www.virustotal.com/de/file/e96f2e7eb80c162c2e5998decc15f26615c9fc76efec73379dd2e2140e4eba08/analysis/1468952442/

如果你们可以测试 exe 和测试项目,这将很有帮助,这可能会导致问题与计算机相关或与已安装的 IDE/生成的 exe 相关。这当然只有在有人可以重现该问题的情况下。

使用此 exe,应用程序会在商业环境中的两台 Windows 7 x64 Enterprise 计算机上崩溃。但是,它不会在我的装有 Windows 8.1 x64 Prof. 的私人计算机上崩溃。

现在我处于死胡同,慕尼黑城外似乎没有人能够重现这个问题,但我们肯定在两台不同的计算机上都有它。

该问题也提交给 Embarcadero(需要登录): https ://quality.embarcadero.com/browse/RSP-15019

可悲的是,目前,这是我们使用 VCL 样式的一个商店停止器。

4

1 回答 1

2

我找到了解决崩溃的方法。经过一番调试,发现每次在 VCL 样式的 TComboBox 上使用负参数调用 TBitmap::SetSize 时都会发生异常。

请参阅所附屏幕截图中的调用堆栈:

TComboBoxStyleHook::ListBoxWndProc
TComboBoxStyleHook::DrawListBoxVertScroll
TBitmap::SetHeight
TBitmap::SetSize

在此处输入图像描述

在 Vcl.Graphics.pas 中编辑 SetSize() 以退出负数后,异常似乎消失了。这不是解决异常原因的方法,因为为什么在 DrawListBoxVertScroll 中将参数设置为 -1 仍然未知(错误?,也可能是该例程中更多子调用的结果),但至少它是防止异常的修复。在我们所有发生异常的机器上进行了测试,结果是积极的。

不过,很想听听一些真正的 VCL 专家(如 Remy Lebeau 甚至 VCL 开发人员)的意见。

再次,我意识到不是每个人都可以重现异常,但是通过上面链接的测试项目,异常在我们的系统上是不可避免的。

于 2016-07-25T17:21:14.947 回答