gpt4 book ai didi

c++ - 为什么Webkit运行时pow()计算错误?

转载 作者:可可西里 更新时间:2023-11-01 15:20:07 24 4
gpt4 key购买 nike

我有一个 Qt C++ 应用程序,其中有一个 GUI 线程,其中进行了一些浮点计算。它还会打开 QWebView,其中有一个带有一些视频的 Flash 播放器。

很明显,QWebView 的关闭会干扰新的下一个浮点运算。所以 pow(double, double) 返回确定但不正确的值。

在一种情况下,它返回的值是正确值的 1000 倍。还有一次,当与参数 pow(10.0, 2.0) 一起使用时,它返回 1.#inf

我不得不提一下,它是在不同的计算机上测试的,并不特定于特定的 CPU。

对于如何定位Webkit中协处理器出错的地方以及如何预防,您有什么建议吗?

示例(仅限 x64)

环境:Qt 4.7.4、C++、HTML 和 flowplayer

立方米

wrongpow::wrongpow(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
QVBoxLayout* layout = new QVBoxLayout(0);
m_view = new QWebView(this);
m_view->setMinimumSize(400, 400);
m_view->settings()->setAttribute(QWebSettings::PluginsEnabled, true);
m_view->settings()->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls, true);
layout->addWidget(m_view);
QDir dir(QApplication::applicationDirPath());
dir.cd("media");
m_view->load(QUrl(QFileInfo(dir, "index.html").absoluteFilePath()));

QPushButton* button = new QPushButton(QLatin1String("Click on video start"), this);
layout->addWidget(button);
Q_ASSERT(connect(button, SIGNAL(clicked()), this, SLOT(closeView())));

setLayout(layout);
adjustSize();
}
Q_SLOT void wrongpow::closeView()
{
delete m_view;
m_view = NULL;

double wrongResult = pow(10.0, 2.0);
Q_ASSERT(wrongResult == 100.0);
}

html

<div id='player' style='width:100%; height:100%;'>
<object width='100%' height='100%' id='_494187117' name='_494187117' data='js/plugins/flowplayer-3.2.18.swf' type='application/x-shockwave-flash'>
<param name='wmode' value='opaque'>
<param name='flashvars' value='config={&quot;clip&quot;:{&quot;url&quot;:&quot;mp4:vod/demo.flowplayer/buffalo_soldiers.mp4&quot;,&quot;scaling&quot;:&quot;fit&quot;,&quot;provider&quot;:&quot;hddn&quot;,&quot;live&quot;:true},&quot;plugins&quot;:{&quot;hddn&quot;:{&quot;url&quot;:&quot;js/plugins/flowplayer.rtmp-3.2.13.swf&quot;,&quot;netConnectionUrl&quot;:&quot;rtmp://r.demo.flowplayer.netdna-cdn.com/play&quot;}},&quot;canvas&quot;:{&quot;backgroundGradient&quot;:&quot;none&quot;}}'>
</object>
</div>

这是一个完整的源程序: Download 15MB

最佳答案

pow 结果不正确的原因是 x87 寄存器 ST0-ST3 变成了 1#SNAN,因此 TAGS = 0xFF。它发生在销毁包含视频 Flash 对象的 QWebView 期间。 x87 和 SSE 的控制字包含正确的值。已测试 Adove Flash 库:NPSWF64_14_0_0_125.dll

它发生在 WebCore::PluginView::stop 方法调用 Adob​​e Flash 插件对象的析构函数时。

NPError npErr = m_plugin->pluginFuncs()->destroy(m_instance, &savedData);

这是破坏寄存器的程序 (NPSWF64.dll)(实际上它使用与 x87 寄存器关联的 MMX 寄存器):

mov         qword ptr [rsp+8],rcx 
mov qword ptr [rsp+10h],rdx
mov qword ptr [rsp+18h],r8
push rsi
push rdi
push rbx
mov rdi,qword ptr [rsp+20h]
mov rsi,qword ptr [rsp+28h]
mov rcx,qword ptr [rsp+30h]
cmp rcx,20h
jle 000000002F9D8A2D
sub rcx,20h

// writes wrong values to the registers:
movq mm0,mmword ptr [rsi]
movq mm1,mmword ptr [rsi+8]
movq mm2,mmword ptr [rsi+10h]
movq mm3,mmword ptr [rsi+18h]

add rsi,20h
movq mmword ptr [rdi],mm0
movq mmword ptr [rdi+8],mm1
movq mmword ptr [rdi+10h],mm2
movq mmword ptr [rdi+18h],mm3
add rdi,20h
sub rcx,20h
jge 000000002F9D89F1
add rcx,20h
rep movs byte ptr [rdi],byte ptr [rsi]
pop rbx
pop rdi
pop rsi
ret

为防止此错误导致的 pow 计算错误,需要恢复寄存器值。我使用最简单的方法来做到这一点。当插件被销毁时,我用一些参数调用 pow 并恢复寄存器。下次调用就正确了。
有一种更复杂(但可能是正确的)方法可以通过使用 float.h 库中的方法将新值写入寄存器来完成相同的操作。

关于c++ - 为什么Webkit运行时pow()计算错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24795928/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com