Если исходное изображение имеет значение maxnum, превышающее фактическое количество элементов в его списке изображений, то цикл будет выполняться после конца массива source.imagelist. Возможно, maxnum инициализируется значением 1, в то время как массив начинается пустым (или maxnum может вообще не инициализироваться), или, если у вас есть функция Scene :: remove_image (), он мог удалить запись списка изображений без уменьшения MAXNUM. Я бы предложил использовать std :: vector вместо необработанного массива. Вектор будет отслеживать свой собственный размер, поэтому ваш цикл for будет:
for(int i=0; i<source.imagelist.size(); i++)
и он получит доступ только к тому количеству элементов, которое содержится в исходном векторе. Другое возможное объяснение сбоя заключается в том, что один из ваших указателей в source.imagelist принадлежит удаленному изображению, но указатель никогда не был установлен в NULL и теперь является висящим указателем.
delete source.imagelist[4];
...
... // If source.imagelist[4] wasn't set to NULL or removed from the array,
... // then we'll have trouble later.
...
for(int i=0; i<maxnum; i++)
{
if (source.imagelist[i] != NULL) // This evaluates to true even when i == 4
{
// When i == 4, we're reading the xcoord member from an Image
// object that no longer exists.
imagelist[i]->xcoord = source.imagelist[i]->xcoord;
Эта последняя строка будет обращаться к памяти, чего не должно быть. Возможно, объект все еще существует в памяти, потому что он еще не был перезаписан, или, возможно, он был перезаписан, и вы получите недопустимое значение xcoord. Если вам повезет, то ваша программа просто рухнет. Если вы имеете дело непосредственно с new и delete, убедитесь, что вы установили указатель на NULL после его удаления, чтобы у вас не было висящего указателя. Это не предотвращает эту проблему, если вы храните копию указателя где-то, однако, в этом случае вторая копия не будет установлена в NULL, когда вы удаляете-и-NULL первую копию. Если вы позже попытаетесь получить доступ ко второй копии указателя, у вас не будет возможности узнать, что он больше не указывает на действительный объект.
Гораздо безопаснее использовать класс интеллектуальных указателей, и это позволит вам управлять памятью. В стандартной библиотеке C ++ есть умный указатель, называемый std :: auto_ptr, но он имеет странную семантику и не может использоваться в контейнерах C ++, таких как std :: vector. Если у вас установлены библиотеки Boost , то я бы предложил заменить ваши необработанные указатели на boost :: shared_ptr.