Си++: теряется указатель на данные

Тема в разделе "LANGS.C", создана пользователем varnie, 8 фев 2007.

  1. varnie

    varnie New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2005
    Сообщения:
    1.785
    как сделать так, чтобы при создании указателя на пару std::pair<int,someClass*>*, предварительно получив указатель на someClass через new, в дальнейшем при обращении извне (совсем из другого класса) к someClass* через second, этот someClass* не терялся?
    я так подозреваю, все дело в том, что при создании someClass* через new, после выхода из этого метода, где я его создаю, указатель на него теряется. как это предотвратить?
    благодарю за наставление на путь истинный.

    ps: если вместо std::pair<int,someClass*>* юзать std::pair<int,someClass*> то все ок.
     
  2. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    varnie
    [off]
    До Штирлица не дошла шифровка из центра. Он прочитал ее еще раз. Опять не дошла. :)
    [/off]
    Что именно теряется? Указатель? Значение указателя? Объект, на который он указывает?
    Что именно значит "теряется"? Недоступность? Некорректность?
    Приведи фрагмент исходника, что ли...
     
  3. varnie

    varnie New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2005
    Сообщения:
    1.785
    есть следующее:

    Код (Text):
    1. typedef std::pair<int, myDataClass*> myDataClassEntry;
    2. typedef std::map<std::string, myDataClassEntry*> dataClassEntries;
    3. typedef std::map<std::string, myDataClassEntry*>::value_type valType;
    4.  
    5.  
    6. class myBuggyClass
    7. {
    8.    public:
    9.       //..
    10.       bool addInfo() const;
    11.       const myDataClassEntry *getData(const std::string &name) const;
    12.    private:
    13.       dataClassEntries data;
    14. };
    15.  
    16. bool myBuggyClass::addInfo() const
    17. {
    18.     //..
    19.     //получили ID
    20.     int ID = 10; //не суть важно
    21.     //получили pcurData
    22.     myDataClass *pCurData = new myDataClass(); //не суть важно
    23.  
    24.     myDataClassEntry test = std::make_pair(id,pCurData);
    25.     myDataClassEntry *pTest = &test;
    26.  
    27.     data.insert( valType(name, pTest ) );
    28. }
    29.  
    30. const myDataClassEntry *myBuggyClass::getData(const std::string &name) const
    31. {
    32.    // такие данные есть?  
    33.    dataClassEntries::const_iterator it = data.find(name);    
    34.    if ( it != data.end() )        
    35.      return it->second;  
    36.  
    37.    //нету
    38.    return NULL;
    39. }
    //-------------------

    далее есть другой класс и в нем в одном из методов нужно получить доступ к определенным myDataClassEntry, хранящимся в приватной переменнной data вышерасписанного класса myBuggyClass.

    Код (Text):
    1. void anotherClass::getData() const
    2. {
    3.      static const myDataClassEntry *entry curBuggyClass->getData("BACKGROUND");
    4.  
    5.      if (!entry->second)
    6.      {
    7.         printf("no such data!\n");
    8.         ::exit(-1);
    9.      }
    10.      else
    11.      {
    12.        //далее идет логика программы, если все ок
    13.      }
    14.  
    15. }
    если я определяю dataClassEntries и myDataClassEntry как выше (c использованием myDataCLass*), то почему-то в этом методе постоянно в imgBackground->second пусто (выводится "no such data" и прога звершает свою работу), а если же мои данные имеют вид
    typedef std::pair<int, myDataCLass> myDataClassEntry;
    typedef std::map<std::string, myDataClassEntry> dataClassEntries;
    typedef std::map<std::string, myDataClassEntry>::value_type valType;
    и все переписано соответствующе, то код идет на ура, и в imgBackground.second всегда правильные данные и прога далее исполняется.

    вот и не пойму, почему так и где я напортачил.
     
  4. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    а напортачил вот здесь:
    Код (Text):
    1. bool myBuggyClass::addInfo() const
    2. {
    3.     //..
    4.     //получили ID
    5.     int ID = 10; //не суть важно
    6.     //получили pcurData
    7.     myDataClass *pCurData = new myDataClass(); //не суть важно
    8.  
    9.     myDataClassEntry test = std::make_pair(id,pCurData);
    10.     myDataClassEntry *pTest = &test;
    11. //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    12.     data.insert( valType(name, pTest ) );
    13. }
    У тебя создается автоматический объект. Берется его адрес. Запихивается в контейнер. Затем addInfo завершается. Объект уничтожается, ибо автоматический. Указатель остается. Указывает в космос.
    Во втором случае в контейнере лежат не указатели, а сами объекты. Поэтому при вызове insert объект, а не указатель копируется в контейнер.
    Если хочешь хранить указатели тогда придется написать что-то вроде:
    Код (Text):
    1.     myDataClass *pCurData = new myDataClass();
    2.     myDataClassEntry *pTest = new myDataClassEntry(id, pCurData);
    3.     data.insert( valType(name, pTest ) );
    и позаботиться об освобождении после - иначе утечка памяти.
    Проверять же указатели в С++ - дохлый номер, реализация не обязана заботится об его корректности, это тебе не Java.
     
  5. varnie

    varnie New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2005
    Сообщения:
    1.785
    Ustus,
    спасибо за прояснение ситуации!
    я кстати так сразу и подумал, что дело в этом автоматическом объекте, но почему-то не был уверен.
    воспользовался вашим предложенным решением - заработало!! и без всяких новых классов обошелся:)

    еще вопрос - как мне быть уверенным, что при уничтожении объекта, на который указывает мой pTest произойдет корректное освобождение занятой им памяти? достаточно ли будет того, что у меня в деструкторе этого класса будет освобождение памяти через delete ? я это почему спрашиваю - по логике моей программы, удаление этого класса должно выполняться фактически только при завершении проги.
    как мне быть, положиться на средства си++ (деструкторы) для соотв. класса, или же еще что-то можно предпринять? у меня в деструкторе этого класса стоит data.clear(); data = NULL;
    этого хватит или нет?
     
  6. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    Насколько я смог понять, тебя интересует, освободится ли память при очищении map? Нет. Освобождается лишь выделенная под элементы std::pair. Для освобождения указателей myDataClass* нужно освобождать их самому:
    Код (Text):
    1. for(dataClassEntries::iterator iter = data.begin(); iter != data.end(); iter++)
    2.   delete iter->second;
    3. data.clear();
     
  7. varnie

    varnie New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2005
    Сообщения:
    1.785
    да, это и имел ввиду. спасибо за помощь.:)
    осталось понять, будет ли такого удаления достаточно, если я эту "очистку памяти" data размещу в деструкторе класса, в данных которого эта data и лежит, или же есть более правильное решение?
     
  8. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    В деструкторе этому и место. Почитай Страуструпа что ли?
     
  9. varnie

    varnie New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2005
    Сообщения:
    1.785
    вас понял.
    да читал я Страуструпа и еще много чего, просто че-то заклинило и все.
    ну, теперь расклинило и все встало на свои места.