singlepost

область памяти улетает на юг … << На главную или назад  

Доброго времени суток , товарищи . Кому не охота читать про нубовские проблемы , – переходите к другой теме . Не нужно унылых придирок , ибо я только учусь . Собственно , объективной критике всегда рад .

Сабж :
Методом волшебного ретурна через 2 класса передается указатель на экземпляр маленького класса , представляющего из себя пулю в комп.игре . Дальше этот адресок уходит в глобальную переменную . После этого его можно успешно использовать , но на следующей итерации цикла обработки сообщений в этом участке памяти оказывается "каша" . Члены класса приватные , и никакие методы , кроме конструкторов не занимаются их инициализацией . Проверено : конструкторы не вызываются без контрольно , указатель(глобальный) не переписывается. Я в замешательстве . Может , я чего то не учитываю при работе с указателями\ссылками ?

Код не привожу по причине обьемности .

29 ответов в теме “область памяти улетает на юг …”

  1. 15
    Роман Волошин ответил:

    Спасибо большое , объяснили доходчиво . Переделаю , с учетом всех этих деталей .
    Еще раз спасибо за доходчивость , оперативность и примеры .

  2. 14
    Константин Смотритель ответил:

    Павел, ну а мы о чём тут гутарим? О_о

  3. 13
    Владимир Шалимов ответил:

    Все, дошло… заклинило на &…

  4. 12
    Павел Линт ответил:

    Либо методы должны возвращать указатель, либо testb должен быть не указателем, а экземпляром класса.

    1) GBullet* GWeapon::shoot(MyPOINT wsrc , MyPOINT wdest)
    {

    return new GBullet(texbank->getTex(t) , wsrc , wdest , bullspeed , damage);
    }

    2) GBullet* SunPlayer::shoot(POINT mouse)
    {

    return new GBullet( bullet->shoot(pos , m) );
    }

    3) testb = player->shoot(mouse->getPos());

  5. 11
    Константин Смотритель ответил:

    Это указатель (возможно, умный), т.к. используется -> а не .
    Или ты о чём?…

  6. 10
    Константин Смотритель ответил:

    Вероятно, в архитектуре т.с. этот указатель инициализируется аналогично testb

  7. 9
    Константин Смотритель ответил:

    Да, Владимир написал тоже подходящий вариант – копирование объекта и в глобальную переменную, но объём операций в этом случае больше, чем при использовании умных указателей. Но оба варианта рабочие, и если класс небольшой – почему бы нет?

    Конечно, проблема удаления объекта остаётся в обоих случаях. Боюсь, проще переделать архитектуру.

    PPS. Владимир, вероятно, да (но ссылка на итерации, полагаю, не столь важна =)

  8. 8
    Владимир Шалимов ответил:

    Константин, а зачем в вашем примере
    —————————
    3)
    static PBullet testb;

    SunPlayer* player = …; //вот здесь создается указатель? У топостартера, очевидно, тут просто объект.

    testb = player->shoot(mouse->getPos());
    —————————

  9. 7
    Константин Смотритель ответил:

    Пример корректного кода (псевдокод!):

    typedef boost::shared_ptr<GBullet> PBullet;

    1) PBullet GWeapon::shoot(MyPOINT wsrc , MyPOINT wdest)
    {

    PBullet bull = new GBullet(texbank->getTex(t) , wsrc , wdest , bullspeed , damage);
    return bull;
    }

    2) PBullet SunPlayer::shoot(POINT mouse)
    {
    GWeapon bullet(…);

    return bullet->shoot(pos , m);
    }

    3)
    static PBullet testb;

    SunPlayer* player = …;

    testb = player->shoot(mouse->getPos());

    Здесь есть скрытая проблема, заключающаяся в, что testb после последней инициализации будет уничтожен только при выходе из программы (но это уже вопрос твоей архитектуры – будет ли это всё корректно).

    Вообще, может тебе нужен паттерн Синглтон? С возможностью замены синглтона =) Хотя, навряд-ли =)

    Если что, смотри или Синглтон Майерса, или мой вариант //www.rsdn.ru/?/Frame/Main.aspx

  10. 6
    Владимир Шалимов ответил:

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

    Внутри итерации, судя по всему, вы создаете маленький объект GBullet bull. Этот объект – локальный, и стирается при выходе из итерации. Тот факт, что вы где-то сохранили указатель на место, где этот объект лежал, никого не волнует. Если этот объект вам нужен дальше, копируйте объект целиком (не указатель, а сам объект), или перестройте программу так, чтобы объект создавался ДО цикла (впоследствии, допустим, заполняя его нужными данными)

    PS. Да, или как у Константина – память, выделенная с помощью new, чистится только с помощью delete, и никак иначе

    PPS. Я правильно понял, что фрагмент 3) у топостартера более полно выглядит так:
    ————————————-
    GBullet* testb;
    ….
    while(…){

    testb = &player->shoot(mouse->getPos());

    }
    ————————————-
    ?

  11. 5
    Константин Смотритель ответил:

    В общем случае необходимо использовать создание объекта с помощью new. И лучше использовать умный указатель – например, boost::shared_ptr. Если этого не сделать, то надо будет заботиться об удалении объекта.

    А вообще, хорошо бы подумать на предмет отказа от использования глобальной переменной – нельзя ли поместить GBullet в какой-либо класс иерархии?…

  12. 4
    Константин Смотритель ответил:

    В 1 передаётся не указатель, а сам "маленький класс" (если это С++, конечно). В 2 непонятно, что происходит (нужно указать тип bullet и раскрыть метод shoot). В 3 тоже непонятно, какой тип имеет player

    Также интересно, как устроен конструктор копирования GBullet

  13. 3
    Константин Смотритель ответил:

    Если предположить, что в 2 bullet имеет тип GWeapon, а в 3 player имеет тип SunPlayer, то возвращённый объект GBullet, во-первых, будет получен посредством конструктора копирования, во-вторых, умрёт сразу же на выходе за пределы содержащего вызов 3 блока.

    Понятно объяснил?….

  14. 2
    Роман Волошин ответил:

    1) GBullet GWeapon::shoot(MyPOINT wsrc , MyPOINT wdest)
    {

    GBullet bull(texbank->getTex(t) , wsrc , wdest , bullspeed , damage);
    return bull;
    }

    2) GBullet SunPlayer::shoot(POINT mouse)
    {

    return bullet->shoot(pos , m);
    }

    3) testb = &player->shoot(mouse->getPos());

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

  15. 1
    Николай Митропольский ответил:

    Ну без кода конечно трудно…
    Банально: Вы уверены что ваша пуля "доживает" до следующей итерации цикла?

Клуб программистов работает уже ой-ой-ой сколько, а если поточнее, то с 2007 года.