为什么Safari页面破坏了iOS渲染?


79

我知道标题不是解释性的,而是故事:我正在开发一种浏览器游戏,主要使用JavaScript和Mapbox库。

一切在台式机,Android和iOS上都可以正常运行,但是在iOS上出现了一个问题:让游戏运行了几分钟后,手机突然开始出现图形伪像,并显示了大部分乱码。

这是手机开始时的一些照片: 在此处输入图片说明 在此处输入图片说明 在此处输入图片说明

我的问题是:代码中到底是什么原因引起的?内存泄漏?(LE:事实证明实际上是内存泄漏)
真正的问题是:为什么只通过浏览网页就可以几乎将整个手机变成砖块?Safari是否应该停止此操作,或者至少是iOS?

这不是此特定设备的问题,因为此问题可以在其他iPhone设备上重现。(我不太确定不同的iOS版本)。

如何重现错误:

  1. 打开游戏(在Safari内部)。
  2. 让它运行3-4分钟。
  3. 向下滑动通知中心,一切都会变得疯狂。
    我添加了一个YouTube视频,该视频显示了如何重现错误(在iPhone 5C上)。
    该问题似乎首先出现在通知中心中(如果您从顶部向下滑动菜单)。
    就目前而言,此问题似乎仅在iPhone 5CiOS 9.2.1(13D15)上发生。它也发生在新的iOS 9.3版本上。

为了解决此问题,我必须:

  1. 关闭Safari应用程序(在其中打开了游戏选项卡)。
  2. 锁定手机。解锁后,一切恢复正常。

有关游戏本身的一些详细信息:

  1. 游戏会显示一个Mapbox地图及其上方的一些单位(标记)。
  2. Node.js服务器以1节拍/秒的速度运行,并且在每个节拍之后,更新的游戏状态通过Socket.io发送到浏览器。
  3. 每次浏览器收到游戏状态时,都会相应地更新标记。
  4. *如果您放大或缩小标记或选择标记,游戏可能还会更新标记。

EDIT2: 发现内存泄漏(按预期方式)。修复此泄漏(检查undefined_icon)之后,该问题不再发生。这意味着,沿着这些路线的某个地方会触发Safari / iOS错误。

对于每个群集的单位(在MarkerCluster中被隐藏并与其他单位分组),这就是每个刻度线的确切名称:

    var $icon = $(marker._icon); // marker._icon is undefined because of the clustering

    $icon.html('');

    $icon.append($('<img class="markerIcon" src="' + options.iconUrl + '" />'));

    var iconX = 10;
    var iconY = -10;
    var iconOffset = 0;

    for(var v in this.icons) {
        this.icons[v].css('z-index', + $icon.css('z-index') + 1);
        this.icons[v].css('transform', 'translate3d(' + iconX + 'px,' 
                                + (iconY + iconOffset) + 'px,' + '0px)');
        iconOffset += 20;

        this.icons[v].appendTo($icon);
    }

    // Fire rate icons
    this.attackRateCircle = $('<div class="circle"></div>');
    this.attackRateCircle.circleProgress({
        value: 0,
        size: 16,
        fill: { color: "#b5deff" },
        emptyFill: 'rgba(0, 0, 0, 0.5)',
        startAngle:  -Math.PI / 2,
        thickness: 4,
        animation: false,
    });
    this.attackRateCircle.hide();

    // Create and display the healthbar
    this.healthBar = $('<div>').addClass('healthBar ');
    this.healthBar.css('z-index', $icon.css('z-index'));
    this.healthBarFill = $('<span class="fill">');
    this.healthBar.append(this.healthBarFill);

    $icon.append(this.healthBar);
    $icon.append(this.attackRateCircle);

这是icons数组:

this.icons = {
    attack_order: $('<img src="img/attack.png" class="status_icon">'),
    attack: $('<img src="img/damage.png" class="status_icon icon_damage">'),
    hit: $('<img src="img/hit.png" class="status_icon icon_hit">'),
};

circleProgress调用来自此库:https : //github.com/kottenator/jquery-circle-progress

演示

是的,我已经能够创建一个重现该错误的jsFiddle:https ://jsfiddle.net/cte55cz7/14/ 在iPhone 5C的Safari上打开并等待几分钟。在iPhone 6和iPad mini上,页面崩溃(如预期的那样,由于内存泄漏)

对于任何不想运行它的人,这都是HasteBin中的相同代码。


2
PS:因在上发布问题而被否决后,在SO上发布SuperUser。我希望这被认为是提出这个问题的正确地方。
XCS

2
@wottle我在我的iPhone 5C上进行了测试,另一个人(在另一个大陆:D上)在另一部iPhone上进行了测试,但是我认为他的模型也是5C(他是真正告诉我这些假象的人)。我明天将在iPhone 6和iPad mini上进行测试。
XCS

2
无法在我的iPhone 6上重现。这可能是CG中的错误。您可以发布所有ios版本信息以及硬件信息吗?
Fresheyeball

2
哇!而且我认为Windows 10移动版上的屏幕撕裂是不好的……
BoltClock

6
A)我什至不生气。太棒了。B)我有点想知道这是否真的可以用作漏洞利用,因为您显然正在访问您不应该访问的内存,并且C)我认为一切都总是向左倾斜很有趣。这向我暗示,由于某种原因,您正在增加某些纹理的间距(又称步幅)或修改GPU的间距逻辑。绝对是Safari / iOS /固件错误。
0x24a537r9

Answers:


1

这种内存泄漏可能是由于“ WebKit的JS引擎”的工作原理引起的[safari webkit-javascript llvm]

确实看起来像是虚拟内存缓冲区溢出,对剩余的RAM有直接影响(iOS也共享并使用它来存储用户界面图形元素)

相对于一段代码:“ [...]查找jQuery内存泄漏很容易。检查$ .cache的大小。如果它太大,请检查它并查看保留哪些条目以及为什么。[...]”(http://javascript.info/tutorial/memory-leaks

我希望它是与此for循环相关的

for(var v in this.icons) {
    this.icons[v].css('z-index', + $icon.css('z-index') + 1);
    this.icons[v].css('transform', 'translate3d(' + iconX + 'px,' 
                            + (iconY + iconOffset) + 'px,' + '0px)');
    iconOffset += 20;

    this.icons[v].appendTo($icon);
}

假设已完成检查,并假设您已找到条目,则可能要使用removeData()手动清除数据, 或者可以先使用$ elem.detach(),然后再使用$(elem).remove()在setTimeout中。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.