changeset 17425:e17aa0669957 draft

(svn r22175) -Fix: [NewGRF] memory leak if a station newgrf contains prop 09 twice for the same station id
author yexo <yexo@openttd.org>
date Thu, 03 Mar 2011 21:24:03 +0000
parents 1743785811ce
children a453c01574b5
files src/newgrf.cpp src/newgrf_station.h src/sprite.cpp src/sprite.h src/table/station_land.h
diffstat 5 files changed, 33 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/src/newgrf.cpp
+++ b/src/newgrf.cpp
@@ -1199,7 +1199,6 @@
 			case 0x09: // Define sprite layout
 				statspec->tiles = buf->ReadExtendedByte();
 				statspec->renderdata = CallocT<DrawTileSprites>(statspec->tiles);
-				statspec->copied_renderdata = false;
 
 				for (uint t = 0; t < statspec->tiles; t++) {
 					DrawTileSprites *dts = &statspec->renderdata[t];
@@ -1208,7 +1207,12 @@
 					dts->seq = NULL;
 					dts->ground.sprite = buf->ReadWord();
 					dts->ground.pal = buf->ReadWord();
-					if (dts->ground.sprite == 0) continue;
+					if (dts->ground.sprite == 0 && dts->ground.pal == 0) {
+						extern const DrawTileSprites _station_display_datas_rail[8];
+						dts->ground = _station_display_datas_rail[t % 8].ground;
+						dts->seq = CopyDrawTileSeqStruct(_station_display_datas_rail[t % 8].seq);
+						continue;
+					}
 					if (HasBit(dts->ground.pal, 15)) {
 						/* Use sprite from Action 1 */
 						ClrBit(dts->ground.pal, 15);
@@ -1254,8 +1258,11 @@
 				}
 
 				statspec->tiles = srcstatspec->tiles;
-				statspec->renderdata = srcstatspec->renderdata;
-				statspec->copied_renderdata = true;
+				statspec->renderdata = MallocT<DrawTileSprites>(statspec->tiles);
+				for (uint t = 0; t < statspec->tiles; t++) {
+					statspec->renderdata[t].ground = srcstatspec->renderdata[t].ground;
+					statspec->renderdata[t].seq = CopyDrawTileSeqStruct(srcstatspec->renderdata[t].seq);
+				}
 				break;
 			}
 
@@ -7050,13 +7057,10 @@
 			if (stations[i] == NULL) continue;
 			StationSpec *statspec = stations[i];
 
-			/* Release renderdata, if it wasn't copied from another custom station spec  */
-			if (!statspec->copied_renderdata) {
-				for (uint t = 0; t < statspec->tiles; t++) {
-					free((void*)statspec->renderdata[t].seq);
-				}
-				free(statspec->renderdata);
+			for (uint t = 0; t < statspec->tiles; t++) {
+				free((void*)statspec->renderdata[t].seq);
 			}
+			free(statspec->renderdata);
 
 			/* Release platforms and layouts */
 			if (!statspec->copied_layouts) {
--- a/src/newgrf_station.h
+++ b/src/newgrf_station.h
@@ -78,7 +78,6 @@
 	 */
 	uint tiles;
 	DrawTileSprites *renderdata; ///< Array of tile layouts.
-	bool copied_renderdata;
 
 	/**
 	 * Cargo threshold for choosing between little and lots of cargo
--- a/src/sprite.cpp
+++ b/src/sprite.cpp
@@ -14,6 +14,8 @@
 #include "viewport_func.h"
 #include "landscape.h"
 #include "spritecache.h"
+#include "core/alloc_func.hpp"
+#include "core/mem_func.hpp"
 
 
 /**
@@ -108,3 +110,17 @@
 		}
 	}
 }
+
+/** Create a copy of an existing DrawTileSeqStruct array. */
+const DrawTileSeqStruct *CopyDrawTileSeqStruct(const DrawTileSeqStruct *dtss)
+{
+	const DrawTileSeqStruct *element;
+
+	size_t count = 1; // 1 for the terminator
+	foreach_draw_tile_seq(element, dtss) count++;
+
+	DrawTileSeqStruct *copy = MallocT<DrawTileSeqStruct>(count);
+	MemCpyT(copy, dtss, count);
+
+	return copy;
+}
--- a/src/sprite.h
+++ b/src/sprite.h
@@ -52,6 +52,8 @@
 	}
 };
 
+const DrawTileSeqStruct *CopyDrawTileSeqStruct(const DrawTileSeqStruct *dtss);
+
 /** Ground palette sprite of a tile, together with its child sprites */
 struct DrawTileSprites {
 	PalSpriteID ground;           ///< Palette and sprite for the ground
--- a/src/table/station_land.h
+++ b/src/table/station_land.h
@@ -791,7 +791,7 @@
 #define TILE_SPRITE_LINE(img, dtss) { {img, PAL_NONE}, dtss },
 #define TILE_SPRITE_NULL() { {0, 0}, NULL },
 
-static const DrawTileSprites _station_display_datas_rail[] = {
+extern const DrawTileSprites _station_display_datas_rail[] = {
 	TILE_SPRITE_LINE(SPR_RAIL_TRACK_X,               _station_display_datas_0)
 	TILE_SPRITE_LINE(SPR_RAIL_TRACK_Y,               _station_display_datas_1)
 	TILE_SPRITE_LINE(SPR_RAIL_TRACK_X,               _station_display_datas_2)