使用 VCL 样式在 TOpenDialog 中出现异常/崩溃
Using VCL Styles gives a exception / crash in TOpenDialog
我在使用启用了 VCL 样式的简单 TOpenDialog 时遇到崩溃/异常。
如果不启用样式,对话框当然可以正常工作。 C++ Builder 10 和 10.1 Professional 会出现此问题。
重现:
- 创建一个使用样式的简单 VCL 表单
- 在表单中添加一个 TComboBox、一个 TButton 和一个 TOpenDialog
将以下代码添加到按钮的 OnClick 事件中
OpenDialog1->Execute();
for(int i=0; i<100; i++)
ComboBox1->Items->Add("test text");
ComboBox1->ItemIndex = 1;
运行应用程序,点击按钮和select一个文件
- 对我来说,这会导致异常 'Out of system resources'
此错误可以在 Windows 7 Enterprise 和 Windows 8.1 Pro 上重现。
TSaveDialog 也有同样的问题。
对我来说奇怪的是,关于这个异常,我在网上找不到类似的问题。在我看来,只有 VCL 样式和 TOpenDialog 需要这个,我希望网络上有更多关于这个的信息。
我只发现了一些类似的东西,但不是例外,也没有关于原生 VCL 样式的解决方案:
我还尝试禁用 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'
- 运行 程序,按下按钮,select 任何文件和 select 在 TOpenDialog
中确定
在这里,这就是异常所需要的全部内容。
在我看来,对 Execute() 的调用弄乱了一些 VCL 结构(仅当启用样式时),然后访问另一个 VCL 项(在我的例子中是组合框)导致崩溃。
我现在知道并不是每个人都会遇到这种崩溃。所以请原谅我,如果它不是你们每个人 100% 可验证的例子。
但我和我的同事不可能是唯一遇到此崩溃的人(现在在 4 台不同的计算机上测试了 3 个不同的 OS 版本),我们可以吗?
* 编辑 2016/05/27 *
关于Tom B运行berg的单步请求,异常发生在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 应用程序。结果是一样的,它在 select 文件并在对话框中点击 'open' 后立即崩溃。
我在这里上传了测试项目
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/generated exe 相关。这当然只有在有人可以重现问题的情况下才可以。
使用此 exe,应用程序在商业环境中的两台 Windows 7 x64 企业计算机上崩溃。
但是,它不会在我使用 Windows 8.1 x64 Prof.
的私人计算机上崩溃
现在我走投无路了,慕尼黑以外的地方似乎没有人能够重现这个问题,但我们在两台不同的计算机上肯定有它。
这个问题也提交给了 Embarcadero(需要登录):
https://quality.embarcadero.com/browse/RSP-15019
可悲的是,目前,这是我们使用 VCL 样式的障碍。
我找到了解决崩溃问题的方法。经过更多的调试,发现每次在 VCL 样式的 TComboBox 上使用负参数调用 TBitmap::SetSize 时都会发生异常。
请查看随附屏幕截图中的调用堆栈:
TComboBoxStyleHook::ListBoxWndProc
TComboBoxStyleHook::DrawListBoxVertScroll
TBitmap::SetHeight
TBitmap::SetSize
在 Vcl.Graphics.pas 中编辑 SetSize() 以退出负数后,异常似乎消失了。
这不是异常原因的修复,因为为什么在 DrawListBoxVertScroll 中将参数设置为 -1 仍然是未知的(错误?,也可能是此例程中更多子调用的结果),但至少它是
防止异常的修复。在我们所有发生异常的机器上进行了测试,结果是肯定的。
但很想听听一些真正的 VCL 专家(例如 Remy Lebeau)甚至 VCL 开发人员对此的意见。
再一次,我意识到不是每个人都可以重现异常,但是通过上面链接的测试项目,异常在我们的系统上是不可避免的。
我在使用启用了 VCL 样式的简单 TOpenDialog 时遇到崩溃/异常。
如果不启用样式,对话框当然可以正常工作。 C++ Builder 10 和 10.1 Professional 会出现此问题。
重现:
- 创建一个使用样式的简单 VCL 表单
- 在表单中添加一个 TComboBox、一个 TButton 和一个 TOpenDialog
将以下代码添加到按钮的 OnClick 事件中
OpenDialog1->Execute(); for(int i=0; i<100; i++) ComboBox1->Items->Add("test text"); ComboBox1->ItemIndex = 1;
运行应用程序,点击按钮和select一个文件
- 对我来说,这会导致异常 'Out of system resources'
此错误可以在 Windows 7 Enterprise 和 Windows 8.1 Pro 上重现。 TSaveDialog 也有同样的问题。
对我来说奇怪的是,关于这个异常,我在网上找不到类似的问题。在我看来,只有 VCL 样式和 TOpenDialog 需要这个,我希望网络上有更多关于这个的信息。
我只发现了一些类似的东西,但不是例外,也没有关于原生 VCL 样式的解决方案:
我还尝试禁用 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'
- 运行 程序,按下按钮,select 任何文件和 select 在 TOpenDialog 中确定
在这里,这就是异常所需要的全部内容。
在我看来,对 Execute() 的调用弄乱了一些 VCL 结构(仅当启用样式时),然后访问另一个 VCL 项(在我的例子中是组合框)导致崩溃。
我现在知道并不是每个人都会遇到这种崩溃。所以请原谅我,如果它不是你们每个人 100% 可验证的例子。
但我和我的同事不可能是唯一遇到此崩溃的人(现在在 4 台不同的计算机上测试了 3 个不同的 OS 版本),我们可以吗?
* 编辑 2016/05/27 *
关于Tom B运行berg的单步请求,异常发生在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 应用程序。结果是一样的,它在 select 文件并在对话框中点击 'open' 后立即崩溃。
我在这里上传了测试项目 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/generated exe 相关。这当然只有在有人可以重现问题的情况下才可以。
使用此 exe,应用程序在商业环境中的两台 Windows 7 x64 企业计算机上崩溃。 但是,它不会在我使用 Windows 8.1 x64 Prof.
的私人计算机上崩溃现在我走投无路了,慕尼黑以外的地方似乎没有人能够重现这个问题,但我们在两台不同的计算机上肯定有它。
这个问题也提交给了 Embarcadero(需要登录): https://quality.embarcadero.com/browse/RSP-15019
可悲的是,目前,这是我们使用 VCL 样式的障碍。
我找到了解决崩溃问题的方法。经过更多的调试,发现每次在 VCL 样式的 TComboBox 上使用负参数调用 TBitmap::SetSize 时都会发生异常。
请查看随附屏幕截图中的调用堆栈:
TComboBoxStyleHook::ListBoxWndProc
TComboBoxStyleHook::DrawListBoxVertScroll
TBitmap::SetHeight
TBitmap::SetSize
在 Vcl.Graphics.pas 中编辑 SetSize() 以退出负数后,异常似乎消失了。 这不是异常原因的修复,因为为什么在 DrawListBoxVertScroll 中将参数设置为 -1 仍然是未知的(错误?,也可能是此例程中更多子调用的结果),但至少它是 防止异常的修复。在我们所有发生异常的机器上进行了测试,结果是肯定的。
但很想听听一些真正的 VCL 专家(例如 Remy Lebeau)甚至 VCL 开发人员对此的意见。
再一次,我意识到不是每个人都可以重现异常,但是通过上面链接的测试项目,异常在我们的系统上是不可避免的。