如何正确删除版本为Box2dWeb-2.1.a.3、Box2D_v2.3.1r3的box2d主体? Box2D 错误?

2023-12-01

Update

自从发现问题后,我还发现 Box2D for web 到处都有泄漏:/

为了展示这一点,我做了一个在静态多边形中移动的简单圆圈,这是一段时间后的结果。

enter image description here

请注意以下项目是如何泄漏的,因为我没有创建任何主体或以任何方式改变世界:

  • b2Vec2
  • Features
  • b2流形点
  • b2联系人ID
  • b2歧管
  • b2ContactEdge
  • b2PolyAndCircleContact
  • Array
  • ...

原帖

我遇到了问题,因为我正在分析我的游戏,而垃圾收集器不会删除我的身体、联系人和其他内容。然后我查看了他们从 GC 中保留了什么,即 Box2D 本身。这可能会导致两个选择:我做得不好或 Box2D 泄漏。我认为是我的原因。

到底是什么在保留它?

  • contact.m_nodeA.other 似乎是最常用于防止 GC 的。
  • 其他时间:接触中的 m_fixtureB...参见图片

enter image description here enter image description here

你可以看到body有一个__destroyed属性。这是在使用 world.DestroyBody(body) 删除它之前手动设置的

当我摧毁一个物体时,我会在调用世界上的步骤方法后调用它。

正如您从 box2d 方法中看到的那样,它没有删除另一个变量,也没有将其更改为另一个主体,并且我的主体不是 GC。

知道我在这里缺少什么吗?

现在,只有在 world.Step 未运行的情况下我才能解决问题:

var gravity = new Box2D.Vec2(0, 0);
var doSleep = true;
var world = new Box2D.World(gravity, doSleep);
var step = false;

var fixtureDef = new Box2D.FixtureDef();
fixtureDef.density = 1.0;
fixtureDef.friction = 0.5;
fixtureDef.restitution = 0.2;
fixtureDef.shape = new Box2D.PolygonShape();
fixtureDef.shape.SetAsBox(1, 1);
var bodyDef = new Box2D.BodyDef;
bodyDef.type = Box2D.Body.b2_dynamicBody;
bodyDef.position.x = 0.4;
bodyDef.position.y = 0.4;

var bodies = []
var fix = [];
window.c = function(){
    for(var i = 0; i < 100; i++){
        var body = world.CreateBody(bodyDef);
        body._id = i;

        fix.push(body.CreateFixture(fixtureDef));
        bodies.push(body);

    }
    if(step){world.Step(1/60, 3, 3); world.ClearForces();}
    console.log('Created', bodies)
    fixtureDef = null;
    bodyDef = null;
}

window.d = function(){
    _.each(bodies, function(body, i){
        body.DestroyFixture(fix[i]);
        world.DestroyBody(body);

        fix[i] = null;
        bodies[i] = null;
    })
    if(step){world.Step(1/60, 3, 3); world.ClearForces();}
    bodies = null;
    fix = null;
}

将步骤改为true,内存泄漏问题又出现了。

重现内存泄漏问题:

文件中的代码:

var gravity = new Box2D.Vec2(0, 0);
var doSleep = true;
var world = new Box2D.World(gravity, doSleep);

var bodies = []
window.c = function(){
    for(var i = 0; i < 100; i++){
        var bodyDef = new Box2D.BodyDef();
        bodyDef.type = 2;

        var shape = new Box2D.PolygonShape();
        shape.SetAsBox(1, 1);

        var fixtureDef   = new Box2D.FixtureDef();
        fixtureDef.shape = shape;
        var body = world.CreateBody(bodyDef);
        body._id = i;
        body.CreateFixture(fixtureDef);
        bodies.push(body);
    }
    world.Step(0.3, 3, 3);
    console.log('Created', bodies)
}
window.d = function(){
    _.each(bodies, function(body, i){
        world.DestroyBody(body);
        bodies[i] = null;
    })
    world.Step(0.3, 3, 3);
    bodies = null;
}

打开谷歌浏览器:

  • 然后打开您的个人资料并制作快照。
  • 现在在控制台中运行 c() 方法来创建 100 个实体
  • 现在快照2
  • 在快照中搜索 b2Body,您会发现 100 个对象数
  • 现在运行 d() 删除你所有的身体;
  • 通过单击垃圾桶强制垃圾收集
  • 制作快照 3
  • 搜索 b2Body,您还会发现 100 个对象数

At the last step should only be 0 objects as they have been destroyed. Instead of this you'll find this: enter image description here

现在你可以看到有很多来自 b2ContactEdge 的参考。现在,如果删除代码中的 world.Step 部分,您将只会看到 2 个对正文的引用。

如果删除此行

body.CreateFixture(fixtureDef);

或者使主体静止就不再泄漏。

我的游戏循环

...gameLoop = function(o){
    // used a lot here
    var world = o.world;

    // calculate the new positions
    var worldStepSeconds = o.worldStepMs / 1000;

    // step world
    world.Step(worldStepSeconds, o.velocityIterations, o.positionIterations)

    // render debug
    if(o.renderDebug){
        world.DrawDebugData();
    }

    // always to not accumulate forces, maybe some bug occurs
    world.ClearForces();

    // tick all ticking entities
    _.each(o.getTickEntitiesFn(), function(actor){
        if(!actor) return;
        actor.tick(o.worldStepMs, o.lastFrameMs);
    })


    // update PIXI entities
    var body = world.GetBodyList();
    var worldScale = world.SCALE;
    var destroyBody = world.DestroyBody.bind(world);
    while(body){
        var actor = null;
        var visualEntity = null;
        var box2DEntity = o.getBox2DEntityByIdFn(body.GetUserData());
        if(box2DEntity){
            visualEntity = o.getVisualEntityByIdFn(box2DEntity.getVisualEntityId());
            if(box2DEntity.isDestroying()){
                // optimization
                body.__destroyed = true;
                world.DestroyBody(body);
                box2DEntity.completeDestroy();
            }
        }
        if(visualEntity){
            if(visualEntity.isDestroying()){
                visualEntity.completeDestroy();
            }else{
                var inverseY = true;
                var bodyDetails = Utils.getScreenPositionAndRotationOfBody(world, body, inverseY);
                visualEntity.updateSprite(bodyDetails.x, bodyDetails.y, bodyDetails.rotation);
            }
        }
        // this delegates out functionality for each body processed
        if(o.triggersFn.eachBody) o.triggersFn.eachBody(world, body, visualEntity);

        body = body.GetNext();
    }

    // when a joint is created is then also created it's visual counterpart and then set to userData.
    var joint = world.GetJointList();
    while(joint){
        var pixiGraphics = joint.GetUserData();
        if(pixiGraphics){
            // In order to draw a distance joint we need to know the start and end positions.
            // The joint saves the global (yes) anchor positions for each body.
            // After that we need to scale to our screen and invert y axis.
            var anchorA           = joint.GetAnchorA();
            var anchorB           = joint.GetAnchorB();
            var screenPositionA = anchorA.Copy();
            var screenPositionB = anchorB.Copy();
            // scale
            screenPositionA.Multiply(world.SCALE);
            screenPositionB.Multiply(world.SCALE);
            // invert y
            screenPositionA.y = world.CANVAS_HEIGHT - screenPositionA.y
            screenPositionB.y = world.CANVAS_HEIGHT - screenPositionB.y

            // draw a black line
            pixiGraphics.clear();
            pixiGraphics.lineStyle(1, 0x000000, 0.7);
            pixiGraphics.moveTo(screenPositionA.x, screenPositionA.y);
            pixiGraphics.lineTo(screenPositionB.x, screenPositionB.y);
        }
        joint = joint.GetNext();
    }

    // render the PIXI scene
    if(o.renderPixi){
        o.renderer.render(o.stage)
    }

    // render next frame
    requestAnimFrame(o.requestAnimFrameFn);
}

来自 Box2d 的代码:

b2ContactManager.prototype.Destroy = function (c) {
var fixtureA = c.GetFixtureA();
var fixtureB = c.GetFixtureB();
var bodyA = fixtureA.GetBody();
var bodyB = fixtureB.GetBody();
if (c.IsTouching()) {
this.m_contactListener.EndContact(c);
}
if (c.m_prev) {
c.m_prev.m_next = c.m_next;
}
if (c.m_next) {
c.m_next.m_prev = c.m_prev;
}
if (c == this.m_world.m_contactList) {
this.m_world.m_contactList = c.m_next;
}
if (c.m_nodeA.prev) {
c.m_nodeA.prev.next = c.m_nodeA.next;
}
if (c.m_nodeA.next) {
c.m_nodeA.next.prev = c.m_nodeA.prev;
}
if (c.m_nodeA == bodyA.m_contactList) {
bodyA.m_contactList = c.m_nodeA.next;
}
if (c.m_nodeB.prev) {
c.m_nodeB.prev.next = c.m_nodeB.next;
}
if (c.m_nodeB.next) {
c.m_nodeB.next.prev = c.m_nodeB.prev;
}
if (c.m_nodeB == bodyB.m_contactList) {
bodyB.m_contactList = c.m_nodeB.next;
}
this.m_contactFactory.Destroy(c);
--this.m_contactCount;
}


b2ContactFactory.prototype.Destroy = function (contact) {
    if (contact.m_manifold.m_pointCount > 0) {
        contact.m_fixtureA.m_body.SetAwake(true);
        contact.m_fixtureB.m_body.SetAwake(true);
    }
    var type1 = parseInt(contact.m_fixtureA.GetType());
    var type2 = parseInt(contact.m_fixtureB.GetType());
    var reg = this.m_registers[type1][type2];
    if (true) {
        reg.poolCount++;
        contact.m_next = reg.pool;
        reg.pool = contact;
    }
    var destroyFcn = reg.destroyFcn;
    destroyFcn(contact, this.m_allocator);
}

我也有同样的问题,但我想我知道它从哪里来。

而不是 m_* 尝试函数,例如GetFixtureA()代替m_fixtureA.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何正确删除版本为Box2dWeb-2.1.a.3、Box2D_v2.3.1r3的box2d主体? Box2D 错误? 的相关文章

  • Python 中丢弃图像时出现内存泄漏

    我目前正在用 Python 编写一个简单的棋盘游戏 我刚刚意识到当图像重新加载时 垃圾收集不会从内存中清除丢弃的位图数据 仅当游戏启动或加载或分辨率更改时才会发生这种情况 但它会增加消耗的内存 所以我不能让这个问题得到解决 重新加载图像时
  • 将 gprof 与套接字一起使用

    我有一个程序想用 gprof 进行分析 问题 看起来 是它使用套接字 所以我得到这样的事情 select Interrupted system call 我不久前遇到了这个问题 放弃了 然后继续前进 但我真的希望能够分析我的代码 如果可能的
  • 针对 PyPy 进行优化

    这是后续PyPy 的统计分析器 https stackoverflow com questions 17346226 statistical profiler for pypy 我正在 PyPy 下运行一些 Python 代码 并希望对其进
  • R Shiny Memory Leak - 有关如何查找的建议?

    我正在寻找有关如何识别 R 闪亮程序中内存泄漏的一般想法 我正在努力确定泄漏的确切位置 因此很难重新创建 而且我的代码已经超过 1000 行 我确信它与观察和观察事件有关 但我无法准确指出它 我实际上很喜欢 bborgeser 在这里提出的
  • Xcode C++ 和 Objective-C 重构

    有没有办法refactorXcode 中的混合 C Objective C 代码 我正在使用 Cocos2D 和 Box2D 编写游戏 而 Box2D 是用 C 编写的 因此我编写的每个类都应该具有 mm 扩展名 因此当我尝试例如重命名变量
  • 重复 .ajax 调用导致 jQuery 内存泄漏

    我正在使用以下模式 该模式在 Firefox 中会泄漏内存 function function var callee arguments callee ajax url success function setTimeout callee
  • 从 JVM 线程本地空间卸载 Clojure 变量

    我正在 Clojure 中为 BaseX 编写一个插件 通过 lein uberjar 构建 并包含 Clojure 解释器 在大多数情况下 这效果很好 然而 当通过 BaseX HTTP 实例运行时 评估在 Jetty 的线程池内进行 而
  • java堆空间OutOfMemoryError分析工具

    我正在得到一个OutOfMemoryError Java heap space 我可以使用任何工具来查找根本原因吗 您可以使用一些分析工具 例如 eclipse mat 分析应用程序的堆转储 以查看哪些内容消耗了多少堆 但首先您需要获取应用
  • iPhone应用程序NSNumber内存泄漏

    我遇到了内存泄漏 但我不知道它从哪里来以及如何修复它 在某些时候 我计算两个位置之间的距离 double calc self getDistance location to otherLocation NSNumber distance N
  • 线程关闭期间 Win64 Delphi RTL 中的内存泄漏?

    很长一段时间以来 我注意到我的服务器应用程序的 Win64 版本存在内存泄漏问题 虽然 Win32 版本工作正常 内存占用相对稳定 但 64 位版本使用的内存却定期增加 可能 20Mb 天 没有任何明显的原因 不用说 FastMM4 没有报
  • 在 LINUX 上测量 TLB 未命中的命令

    有人可以指导我使用一个命令来测量 LINUX 上的 TLB 未命中吗 是否可以将轻微页面错误视为 TLB 未命中 您可以使用perf去做这个 前提是你的CPU支持 Use perf list了解可用的计数器 当我拿到这个列表并查找 TLB
  • VS2010分析器:是否可以分析一种特定方法?

    可能有一些方法可以打开和关闭代码分析 或者您可以选择要分析的特定函数吗 您还可以使用分析器的数据收集 API 来启动和停止围绕您感兴趣的方法进行分析 请参阅这篇 MSDN 文章 http msdn microsoft com en us l
  • 1 MB 或更多的 Java 字节数组占用 RAM 的两倍

    在 Windows 10 OpenJDK 11 0 4 x64 上运行以下代码会生成输出used 197 and expected usage 200 这意味着包含 100 万个元素的 200 个字节数组大约占用 200 个字节 200MB
  • 如何研究.NET 中的非托管内存泄漏?

    我有一个通过 MSMQ 运行的 WCF 服务 内存随着时间的推移逐渐增加 表明存在某种内存泄漏 我在本地运行该服务并使用 PerfMon 监视一些计数器 CLR 内存托管堆字节总数保持相对恒定 而进程的私有字节随着时间的推移而增加 这让我相
  • NodeJS 内存增长 - (系统)内存泄漏?

    我在我们的生活环境中遇到了奇怪的内存泄漏 其中 system 堆中的对象不断增长 堆转储 Here is a memory dump where the memory usage grew to 800MB 请注意 该内存保留在Genera
  • 如何以编程方式找出我的 PermGen 空间使用情况?

    我正在尝试诊断java lang OutOfMemoryError PermGen Space在 Sun 的 Hotspot JVM 上运行时出现错误 并且想知道我的程序在不同时刻使用了多少 PermGen 空间 有没有办法以编程方式找出这
  • 通过 clang++ 的 -finstrument-functions 进行 C++ 函数检测:如何忽略内部 std 库调用?

    假设我有一个类似的函数 template
  • 有没有办法分析 WCF 应用程序的性能?

    我们正在尝试测量我们的系统的性能 该系统是一个使用 WCF 调用的 NET 3 5 应用程序 问题是到目前为止 我们无法分析这些调用中的方法 编写了一个 winforms 客户端应用程序来测试我们的系统 我们尝试使用ANTS 4 Profi
  • Java 中清除嵌套 Map 的好方法

    public class MyCache AbstractMap
  • 使用带有终结器的 C++/CLI 定义类时 C# 中的内存泄漏

    当我在 C CLI DLL 中实现一个类时 public ref class DummyClass protected DummyClass some dummy code std cout lt lt hello lt lt std en

随机推荐