使用VCL样式在TOpenDialog中会引发异常/崩溃

3

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

没有启用样式时,对话框当然可以正常工作。该问题发生在C++ Builder 10和10.1 Professional中。

复现步骤:

  1. create a simpe VCL Form that uses styles
  2. add a TComboBox, a TButton and a TOpenDialog to the form
  3. add the following code to the OnClick event for the button

    OpenDialog1->Execute();
    for(int i=0; i<100; i++)
      ComboBox1->Items->Add("test text");
    ComboBox1->ItemIndex = 1;
    
  4. run the application, click the button and select a file

  5. For me, this yields to an exception 'Out of system resources'
这个bug可以在Windows 7 Enterprise和Windows 8.1 Pro上重现。我遇到了一个TSaveDialog的相同问题。
对我来说奇怪的是,在这个异常方面,我在网上找不到类似的问题。我认为,只需要VCL样式和TOpenDialog就能够出现这种情况,我希望在网上能找到更多相关信息。
我只找到了一些类似的东西,但没有异常,并且也没有关于本地VCL样式的解决方案: 使用自定义样式在TOpenDialog中右键单击文件时显示无效字符 我还尝试禁用SystemHooks shDialogs(请参见屏幕截图),这是我在另一个与VCL样式有关的问题中读到的,但没有效果。

code

exception


* 编辑 2016/05/26 *

Remy Lebeau要求提供MCVE。我尝试在问题中提供了所有内容,但为了更清晰明了,这里提供一个MCVE的摘要:

  • create new VCL project with default settings
  • drop a TComboBox, a TButton and a TOpenDialog into the form
  • add the following code to the OnClick event for the button:

    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
    }
    
  • enable a VCL style 'Smokey Quartz Kamri' in the project options

  • run program, press button, select any file and select OK in TOpenDialog
这就是异常所需的全部内容。
在我看来,对Execute()的调用会破坏某些VCL结构(仅在启用样式时),然后访问另一个VCL项目(在我的情况下是combobox)会导致崩溃。
我现在意识到并非每个人都会遇到这种崩溃。如果对于你们每个人来说它不是一个100%可验证的示例,请原谅我。
但是我和我的同事不能是唯一遇到这种崩溃的人(现在在3个不同操作系统版本的4台不同电脑上进行了测试),对吧?
*编辑2016/05/27*
关于Tom Brunberg要求单步执行的请求,在截图中的地址005459F4处发生异常。
如果我继续步进,则会落在TCustomCombo.WndProc的某个位置。之后很难跟进,因为WndProc中有重复的循环,似乎无法到达触发异常的最终位置。

enter image description here

* 2016/05/27第二次编辑 *

好的,我成功确定了崩溃的确切位置。它在VCL.Graphics中的CopyBitmap函数中。在第一张截图中,异常出现在以下行:

Result := GDICheck(CreateCompatibleBitmap(ScreenDC, bmWidth, bmHeight))

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

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

enter image description here

enter image description here


* 2016/07/19 编辑 *

由于这里似乎没有人遇到这个问题,我们进行了不同的尝试: 公司的一位同事在英文环境下进行了全新的 C++ Builder 10.1 Berlin 安装(考虑到德语 IDE 可能是罪魁祸首), 安装后第一件事就是重新创建 StylesCrashTest 应用程序。结果是相同的,在对话框中选择文件并点击“打开”后立即崩溃。 enter image description here

我已经在这里上传了测试项目 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 样式来说是一个重要障碍。

就我所知,在 Windows 7 专业版上使用 Delphi 10 Seattle,我无法重现这个问题。错误信息是否类似于“系统资源不足”?它发生在哪一行? - Tom Brunberg
无法使用Amakrits或Aqua Graphite样式在C++ Builder或Delphi 10.1 Berlin或Seattle中复制。 - Ken White
1
请提供一个最小、完整、可验证的示例 - Remy Lebeau
@KenWhite 这个异常似乎不会在每台电脑上都出现。到目前为止,我的测试有:2台PC Win7企业版,在商业环境中,总是在IDE内外抛出异常。1台PC Win 8.1私人环境,只有在IDE内部抛出异常,在外部运行exe文件则正常。 - Tom Major
@Sam 不,L".." 不会改变任何东西。 - Tom Major
显示剩余13条评论
1个回答

2

我找到了解决崩溃问题的方法。经过更多的调试,发现当在VCL样式的TComboBox上使用负参数调用TBitmap::SetSize时,异常会发生。

请查看附加的截图中的调用堆栈:

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

在此输入图片描述

在编辑Vcl.Graphics.pas中的SetSize()以便在负数时退出后,异常似乎已经消失了。这并不是解决异常原因的方法,因为仍然不清楚为什么在DrawListBoxVertScroll中将参数设置为-1(是否为错误?也可能是该例程中更多的子调用结果),但至少它是预防异常的一种方法。在我们所有出现异常的机器上进行测试,结果都是正面的。

希望能听到像Remy Lebeau或甚至VCL开发人员等真正的VCL专家的意见。

再次说明,我意识到并非每个人都能重现异常,但使用上面链接的测试项目,异常在我们的系统上是不可避免的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接