Skip to content

Commit f223f68

Browse files
committed
[ CID 17030 ] Introduce MCAutoCustomPointerArray to free resources pointed to by array elements.
Fixes memory leak issue.
1 parent 81940cf commit f223f68

2 files changed

Lines changed: 136 additions & 1 deletion

File tree

engine/src/deploy_macosx.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1470,7 +1470,7 @@ static bool MCDeployToMacOSXReadHeader(bool p_big_endian, MCDeployFileRef p_engi
14701470
return MCDeployThrow(kMCDeployErrorMacOSXBadHeader);
14711471

14721472
// Allocate memory for the load commands
1473-
MCAutoArray<load_command*> t_commands;
1473+
MCAutoCustomPointerArray<load_command*, MCMemoryDelete> t_commands;
14741474
if (!t_commands.New(r_header . ncmds))
14751475
return MCDeployThrow(kMCDeployErrorNoMemory);
14761476

libfoundation/include/foundation-auto.h

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,6 +1126,141 @@ template<typename T> class MCAutoArray
11261126
uindex_t m_size;
11271127
};
11281128

1129+
// Version of MCAutoArray that applies the provided deallocator to each element of the array when freed
1130+
template <typename T, void (*FREE)(T)> class MCAutoCustomPointerArray
1131+
{
1132+
public:
1133+
MCAutoCustomPointerArray(void)
1134+
{
1135+
m_ptr = nil;
1136+
m_size = 0;
1137+
}
1138+
1139+
~MCAutoCustomPointerArray(void)
1140+
{
1141+
FreeElements(MCRangeMake(0, m_size));
1142+
1143+
MCMemoryDeleteArray(m_ptr);
1144+
}
1145+
1146+
//////////
1147+
1148+
T* Ptr()
1149+
{
1150+
return m_ptr;
1151+
}
1152+
1153+
uindex_t Size() const
1154+
{
1155+
return m_size;
1156+
}
1157+
1158+
//////////
1159+
1160+
bool New(uindex_t p_size)
1161+
{
1162+
MCAssert(m_ptr == nil);
1163+
return MCMemoryNewArray(p_size, m_ptr, m_size);
1164+
}
1165+
1166+
void Delete(void)
1167+
{
1168+
FreeElements(MCRangeMake(0, m_size));
1169+
1170+
MCMemoryDeleteArray(m_ptr);
1171+
m_ptr = nil;
1172+
m_size = 0;
1173+
}
1174+
1175+
//////////
1176+
1177+
bool Resize(uindex_t p_new_size)
1178+
{
1179+
if (p_new_size < m_size)
1180+
FreeElements(MCRangeMake(p_new_size, m_size - p_new_size));
1181+
1182+
return MCMemoryResizeArray(p_new_size, m_ptr, m_size);
1183+
}
1184+
1185+
bool Extend(uindex_t p_new_size)
1186+
{
1187+
MCAssert(p_new_size >= m_size);
1188+
return Resize(p_new_size);
1189+
}
1190+
1191+
void Shrink(uindex_t p_new_size)
1192+
{
1193+
MCAssert(p_new_size <= m_size);
1194+
Resize(p_new_size);
1195+
}
1196+
1197+
//////////
1198+
1199+
bool Push(T p_value)
1200+
{
1201+
if (!Extend(m_size + 1))
1202+
return false;
1203+
m_ptr[m_size - 1] = p_value;
1204+
return true;
1205+
}
1206+
1207+
//////////
1208+
1209+
T*& PtrRef()
1210+
{
1211+
MCAssert(m_ptr == nil);
1212+
return m_ptr;
1213+
}
1214+
1215+
uindex_t& SizeRef()
1216+
{
1217+
MCAssert(m_size == 0);
1218+
return m_size;
1219+
}
1220+
1221+
//////////
1222+
1223+
void Take(T*& r_array, uindex_t& r_count)
1224+
{
1225+
r_array = m_ptr;
1226+
r_count = m_size;
1227+
1228+
m_ptr = nil;
1229+
m_size = 0;
1230+
}
1231+
1232+
//////////
1233+
1234+
T& operator [] (uindex_t p_index)
1235+
{
1236+
return m_ptr[p_index];
1237+
}
1238+
1239+
const T& operator [] (uindex_t p_index) const
1240+
{
1241+
return m_ptr[p_index];
1242+
}
1243+
1244+
private:
1245+
T *m_ptr;
1246+
uindex_t m_size;
1247+
1248+
void FreeElements(const MCRange &p_elements)
1249+
{
1250+
uindex_t t_end;
1251+
t_end = (uindex_t)MCMin(m_size, p_elements.offset + p_elements.length);
1252+
1253+
for (uindex_t i = p_elements.offset; i < t_end; i++)
1254+
{
1255+
if (m_ptr[i] != nil)
1256+
{
1257+
FREE(m_ptr[i]);
1258+
m_ptr[i] = nil;
1259+
}
1260+
}
1261+
}
1262+
};
1263+
11291264
////////////////////////////////////////////////////////////////////////////////
11301265

11311266
class MCAutoNativeCharArray

0 commit comments

Comments
 (0)