Tilemap/VX: Ensure proxy objects don't outlive their parents

Either of these would previously crash (same for VX):

tm = Tilemap.new
at = tm.autotiles
tm = nil
GC.start
at[0] = Bitmap.new(1, 1)

tm = Tilemap.new
at = tm.autotiles
tm.dispose
at[0] = Bitmap.new(1, 1)

Funnily, this makes RMXP itself crash too, but crashing is
never acceptable except for possibly resource exhaustion.
This commit is contained in:
Jonas Kulla 2014-09-26 18:21:50 +02:00
parent e9d0d0566b
commit 9758e660c4
9 changed files with 41 additions and 12 deletions

View File

@ -94,6 +94,10 @@ RB_METHOD(tilemapInitialize)
rb_iv_set(autotilesObj, "array", ary); rb_iv_set(autotilesObj, "array", ary);
/* Circular reference so both objects are always
* alive at the same time */
rb_iv_set(autotilesObj, "tilemap", self);
return self; return self;
} }

View File

@ -64,6 +64,10 @@ RB_METHOD(tilemapVXInitialize)
rb_iv_set(autotilesObj, "array", ary); rb_iv_set(autotilesObj, "array", ary);
/* Circular reference so both objects are always
* alive at the same time */
rb_iv_set(autotilesObj, "tilemap", self);
return self; return self;
} }

View File

@ -41,6 +41,7 @@ struct
SYMD(tone), SYMD(tone),
SYMD(rect), SYMD(rect),
SYMD(src_rect), SYMD(src_rect),
SYMD(tilemap),
SYMD(tileset), SYMD(tileset),
SYMD(autotiles), SYMD(autotiles),
SYMD(map_data), SYMD(map_data),

View File

@ -42,6 +42,7 @@ enum CommonSymbol
CStone, CStone,
CSrect, CSrect,
CSsrc_rect, CSsrc_rect,
CStilemap,
CStileset, CStileset,
CSautotiles, CSautotiles,
CSmap_data, CSmap_data,

View File

@ -93,13 +93,18 @@ MRB_METHOD(tilemapInitialize)
wrapProperty(mrb, self, &t->getAutotiles(), CSautotiles, TilemapAutotilesType); wrapProperty(mrb, self, &t->getAutotiles(), CSautotiles, TilemapAutotilesType);
mrb_value autotilesObj = mrb_iv_get(mrb, self, getMrbData(mrb)->symbols[CSautotiles]); MrbData &mrbData = *getMrbData(mrb);
mrb_value autotilesObj = mrb_iv_get(mrb, self, mrbData.symbols[CSautotiles]);
mrb_value ary = mrb_ary_new_capa(mrb, 7); mrb_value ary = mrb_ary_new_capa(mrb, 7);
for (int i = 0; i < 7; ++i) for (int i = 0; i < 7; ++i)
mrb_ary_push(mrb, ary, mrb_nil_value()); mrb_ary_push(mrb, ary, mrb_nil_value());
mrb_iv_set(mrb, autotilesObj, getMrbData(mrb)->symbols[CSarray], ary); mrb_iv_set(mrb, autotilesObj, mrbData.symbols[CSarray], ary);
/* Circular reference so both objects are always
* alive at the same time */
mrb_iv_set(mrb, autotilesObj, mrbData.symbols[CStilemap], self);
return self; return self;
} }

View File

@ -241,7 +241,6 @@ struct TilemapPrivate
{ {
Viewport *viewport; Viewport *viewport;
Tilemap::Autotiles autotilesProxy;
Bitmap *autotiles[autotileCount]; Bitmap *autotiles[autotileCount];
Bitmap *tileset; Bitmap *tileset;
@ -1183,6 +1182,9 @@ void ZLayer::finiUpdateZ(ZLayer *prev)
void Tilemap::Autotiles::set(int i, Bitmap *bitmap) void Tilemap::Autotiles::set(int i, Bitmap *bitmap)
{ {
if (!p)
return;
if (i < 0 || i > autotileCount-1) if (i < 0 || i > autotileCount-1)
return; return;
@ -1206,6 +1208,9 @@ void Tilemap::Autotiles::set(int i, Bitmap *bitmap)
Bitmap *Tilemap::Autotiles::get(int i) const Bitmap *Tilemap::Autotiles::get(int i) const
{ {
if (!p)
return 0;
if (i < 0 || i > autotileCount-1) if (i < 0 || i > autotileCount-1)
return 0; return 0;
@ -1215,7 +1220,7 @@ Bitmap *Tilemap::Autotiles::get(int i) const
Tilemap::Tilemap(Viewport *viewport) Tilemap::Tilemap(Viewport *viewport)
{ {
p = new TilemapPrivate(viewport); p = new TilemapPrivate(viewport);
p->autotilesProxy.p = p; atProxy.p = p;
} }
Tilemap::~Tilemap() Tilemap::~Tilemap()
@ -1244,11 +1249,11 @@ void Tilemap::update()
p->tiles.aniIdx = 0; p->tiles.aniIdx = 0;
} }
Tilemap::Autotiles &Tilemap::getAutotiles() const Tilemap::Autotiles &Tilemap::getAutotiles()
{ {
guardDisposed(); guardDisposed();
return p->autotilesProxy; return atProxy;
} }
DEF_ATTR_RD_SIMPLE(Tilemap, Viewport, Viewport*, p->viewport) DEF_ATTR_RD_SIMPLE(Tilemap, Viewport, Viewport*, p->viewport)
@ -1379,4 +1384,5 @@ void Tilemap::setOY(int value)
void Tilemap::releaseResources() void Tilemap::releaseResources()
{ {
delete p; delete p;
atProxy.p = 0;
} }

View File

@ -55,7 +55,7 @@ public:
void update(); void update();
Autotiles &getAutotiles() const; Autotiles &getAutotiles();
Viewport *getViewport() const; Viewport *getViewport() const;
DECL_ATTR( Tileset, Bitmap* ) DECL_ATTR( Tileset, Bitmap* )
@ -68,6 +68,7 @@ public:
private: private:
TilemapPrivate *p; TilemapPrivate *p;
Autotiles atProxy;
void releaseResources(); void releaseResources();
const char *klassName() const { return "tilemap"; } const char *klassName() const { return "tilemap"; }

View File

@ -41,7 +41,6 @@
struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader
{ {
TilemapVX::BitmapArray bitmapsProxy;
Bitmap *bitmaps[BM_COUNT]; Bitmap *bitmaps[BM_COUNT];
Table *mapData; Table *mapData;
@ -358,6 +357,9 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader
void TilemapVX::BitmapArray::set(int i, Bitmap *bitmap) void TilemapVX::BitmapArray::set(int i, Bitmap *bitmap)
{ {
if (!p)
return;
if (i < 0 || i >= BM_COUNT) if (i < 0 || i >= BM_COUNT)
return; return;
@ -378,6 +380,9 @@ void TilemapVX::BitmapArray::set(int i, Bitmap *bitmap)
Bitmap *TilemapVX::BitmapArray::get(int i) const Bitmap *TilemapVX::BitmapArray::get(int i) const
{ {
if (!p)
return 0;
if (i < 0 || i >= BM_COUNT) if (i < 0 || i >= BM_COUNT)
return 0; return 0;
@ -387,7 +392,7 @@ Bitmap *TilemapVX::BitmapArray::get(int i) const
TilemapVX::TilemapVX(Viewport *viewport) TilemapVX::TilemapVX(Viewport *viewport)
{ {
p = new TilemapVXPrivate(viewport); p = new TilemapVXPrivate(viewport);
p->bitmapsProxy.p = p; bmProxy.p = p;
} }
TilemapVX::~TilemapVX() TilemapVX::~TilemapVX()
@ -413,11 +418,11 @@ void TilemapVX::update()
p->aniOffset = Vec2(aniIdxA * 2 * 32, aniIdxC * 32); p->aniOffset = Vec2(aniIdxA * 2 * 32, aniIdxC * 32);
} }
TilemapVX::BitmapArray &TilemapVX::getBitmapArray() const TilemapVX::BitmapArray &TilemapVX::getBitmapArray()
{ {
guardDisposed(); guardDisposed();
return p->bitmapsProxy; return bmProxy;
} }
DEF_ATTR_RD_SIMPLE(TilemapVX, MapData, Table*, p->mapData) DEF_ATTR_RD_SIMPLE(TilemapVX, MapData, Table*, p->mapData)
@ -521,4 +526,5 @@ void TilemapVX::setOY(int value)
void TilemapVX::releaseResources() void TilemapVX::releaseResources()
{ {
delete p; delete p;
bmProxy.p = 0;
} }

View File

@ -54,7 +54,7 @@ public:
void update(); void update();
BitmapArray &getBitmapArray() const; BitmapArray &getBitmapArray();
DECL_ATTR( Viewport, Viewport* ) DECL_ATTR( Viewport, Viewport* )
DECL_ATTR( MapData, Table* ) DECL_ATTR( MapData, Table* )
@ -66,6 +66,7 @@ public:
private: private:
TilemapVXPrivate *p; TilemapVXPrivate *p;
BitmapArray bmProxy;
void releaseResources(); void releaseResources();
const char *klassName() const { return "tilemap"; } const char *klassName() const { return "tilemap"; }