Если для исходного изображения maxnum установлено выше, чем фактическое количество элементов в его списке изображений, то цикл будет выполняться после конца массива source.imagelist. Возможно, maxnum инициализируется значением один, в то время как массив начинается пустым (или maxnum может вообще не инициализироваться), или, может быть, если у вас есть функция Scene::remove_image(), она могла удалить запись списка изображений без уменьшения макс. Я бы предложил использовать 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.
person
Josh Townzen
schedule
09.02.2010