2

我们正在为 Mac OSX (10.8) 开发一个需要使用 JavaScript 库的 Cocoa 应用程序(为什么我们必须使用 JavaScript 很长的故事)。

在演示应用程序中,一切似乎都很好,但是在将代码合并到我们的项目中时,我们可以毫无问题地调用该函数 37 次,然后第 38 次崩溃。

要调用 JS 代码,我们使用 Apple 的 JSWrappers.m(来自 JavaScriptCoreHeadStart 示例)。崩溃的行(带有 EXC_BAD_ACCESS)是 #149:

JSObjectCallAsFunction(self.jsContext, jsFunction, NULL, argumentCount, arguments, NULL);

如上所述,它在第 38 次-callStringJSFunction:withParameters:被调用时崩溃,无论输入是什么(它与任何输入字符串一起崩溃,并且如果在之前的 37 次迭代中使用相同的字符串)。EXC_BAD_ACCESS 不是由输入变量引起的,因为访问它们(例如self.jsContext在该行之前立即调用)是有效的:导致崩溃的是函数调用本身。

我们不知道它可能导致此问题的原因,也不知道如何进行更多调试。有没有人有任何提示?谢谢。

//编辑

我必须纠正自己:它也不适用于“演示应用程序”。即使在这种情况下,代码在我们第 38 次调用时也会崩溃-callStringJSFunction:withParameters:

//编辑2

如果我们在每次调用该函数时重新创建 JSWrappers 对象(和一个新的 JSGlobalContext),它就不会再崩溃了。然而,这使得代码变慢了很多(不足为奇,因为 JS 解释器每次都必须读取脚本 - 这是一个相当大的脚本)。

//编辑3

另一个发现:以 32 位构建应用程序会导致代码崩溃。相反,以 64 位构建可以完美运行:JS 代码在我们希望的任何时候都可以毫无问题地执行。这很奇怪:这可能是 JavaScript Core 框架本身的错误吗?

4

2 回答 2

1

回答我自己的问题。

显然这是 JavaScript Core 中的一个错误(?)。在 32 位二进制文​​件中,由于某些原因,我们调用函数的次数不能超过 37 次(内存问题?)。这些问题不会出现在 64 位二进制文​​件上。

此行为发生在 OSX 10.8.4 上。

于 2013-07-29T14:25:20.313 回答
0

有点旧的线程,但今天有点相关。
我们仍然支持回到 iOS 8.2,发现这个问题在一些 iOS 8.4 用户中出现。一些研究表明,这似乎是此时 iOS 版本的一个错误。

在综合测试中,我-callWithArguments:@[]在多个线程上调用相同的函数(一个 100 计数 for 循环中的新线程)——这将在大多数测试设备上完成,甚至是运行 iOS 9.x 的 32 位 iPod touch。共同点是 iOS 8.x,即使在 iPhone 5S(64 位,1GB RAM)上,也会导致 WTFCrash。

在我们的生产应用程序中,该应用程序确实调用了callWithArguments异步,有时还会同时调用多个线程。似乎多个线程同时调用一个长时间运行的函数并导致问题。然后停止这个,我把它包裹callWithArguments在一个

 @synchronized (<#token#>) {
        <#statements#>
    }

这似乎解决了这个问题,并阻止了所有经过测试的 iOS 版本(8.4、9.x、10.3)以及多种架构的崩溃。由于这些调用是在后台线程上进行的,因此对 UI 没有影响。

虽然这可能不是最优雅的方法/解决方案,但它似乎已经解决了我们的问题,即每天有数十名用户遇到间歇性崩溃。话虽如此,如果有人知道这样做的更好方法,请告诉我。

tl;dr
多个线程调用相同的函数导致它用WTFCrash. 将呼叫包裹在@synchronized锁中似乎可以解决它。

于 2017-06-05T10:07:59.847 回答