Проблема с указателями (только в сборке релиза) - PullRequest
3 голосов
/ 08 ноября 2011

не знаю, как описать это, но здесь я иду:

По какой-то причине, когда я пытаюсь создать релизную версию моей игры для тестирования, аспект создания противника не работает.

Enemies *e_level1[3];
e_level1[0] = &Enemies(sdlLib, 500, 2, 3, 128, -250, 32, 32, 0, 1);
e_level1[1] = &Enemies(sdlLib, 500, 2, 3, 128, -325, 32, 32, 3, 1);
e_level1[2] = &Enemies(sdlLib, 500, 2, 3, 128, -550, 32, 32, 1, 1);

Вот как я создаю своих врагов.Работает нормально, когда в конфигурации отладки, но когда я переключаюсь на конфигурацию выпуска, кажется, что враги не инициализируются правильно.

Мне кажется немного странным, что это работает в отладке, но не в выпуске, любая помощь оценивается в том, что в основном то, что я сделал неправильно.

Ответы [ 5 ]

5 голосов
/ 08 ноября 2011
e_level1[0] = &Enemies(sdlLib, 500, 2, 3, 128, -250, 32, 32, 0, 1);

не делает то, что вы думаете, что делает. Если это вызов конструктора, он создает временный объект и его адрес сохраняется в e_level1 [0]. Когда e_level1 [1] инициализируется, деструктор e_level1 [0], вероятно, уже вызывается.

Вы, вероятно, хотите сделать

Enemies* e_level1[3] = 
    {
        new Enemies(sdlLib, 500, 2, 3, 128, -250, 32, 32, 0, 1) , 
        new Enemies(sdlLib, 500, 2, 3, 128, -325, 32, 32, 3, 1) , 
        new Enemies(sdlLib, 500, 2, 3, 128, -550, 32, 32, 1, 1)
    };
3 голосов
/ 08 ноября 2011

Другие люди уже указали на ошибку, а именно на то, что временные блоки уничтожаются сразу, но все ответы до сих пор используют ручное управление памятью - в C ++ более идиоматично использовать, например. std::vector для чего-то подобного, например

std::vector<Enemies> enemies;
enemies.push_back(Enemies(sdlLib, 500, 2, 3, 128, -250, 32, 32, 0, 1));
enemies.push_back(Enemies(sdlLib, 500, 2, 3, 128, -325, 32, 32, 3, 1));
enemies.push_back(Enemies(sdlLib, 500, 2, 3, 128, -550, 32, 32, 1, 1));

Затем вы просто получаете доступ к Enemies экземплярам как enemies[0] через enemies[2], и они автоматически очищаются, когда вектор выходит из области видимости.

2 голосов
/ 08 ноября 2011

Код инициализирует указатели для указания на временные объекты, которые немедленно уничтожаются. Доступ к временным файлам, которые больше не существуют через указатели или ссылки, является неопределенным поведением. Вы хотите:

Enemies *e_level1[3];
e_level1[0] = new Enemies(sdlLib, 500, 2, 3, 128, -250, 32, 32, 0, 1);
e_level1[1] = new Enemies(sdlLib, 500, 2, 3, 128, -325, 32, 32, 3, 1);
e_level1[2] = new Enemies(sdlLib, 500, 2, 3, 128, -550, 32, 32, 1, 1);
2 голосов
/ 08 ноября 2011

Большинство режимов отладки инициализируют всю память на ноль для вас.В обычном исполнении это может быть случайным.

Сделайте ваш компилятор настолько суетливым, насколько это возможно (вы уже должны были это сделать) и исправьте все предупреждения.

Если он все еще не устранен, вы должны запустить егов инструменте проверки памяти, таком как valgrind.

0 голосов
/ 08 ноября 2011

Вы, кажется, создаете объект Enemies в стеке, что означает, что в тот момент, когда они выходят за пределы области видимости, ваши указатели e_level1 указывают на объекты, которые были уничтожены. (доказательство: поставьте точку останова в деструкторе класса Enenmies и посмотрите, когда это произойдет) Поэтому, когда вы попытаетесь отменить их ссылку, вы получите мусор.

То, что вы хотите:

for( size_t i = 0; i < 3; i++ )
    e_level1[i] = new Enemies( sdlLib, ... );

Это создаст объект в куче. Это также означает, что вам нужно будет уничтожить объекты, используя:

for( size_t i = 0; i < 3; i++ )
    delete ( e_level + i );
...