Поиск:

Ответ в темуСоздание новой темы Создание опроса
> статические переменные, нюансы использования 
V
    Опции темы
mes
Дата 17.6.2008, 11:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



недавно столкнулся с одной загадкой в двух проявлениях :
1.
Код
 // a.cpp
А& GetA () { static A a; return a; }  
- при вызове этой функции из деструктора главной формы (используется библиотека wxWigdets, но по идеи не суть важно) возврашалась невалидная ссылка - статический обьект был разрушен хотя мы еше в цикле main. 

2. 
Код

class W { 
     typedef  std::map<std::string, W*> WMap;
     static WMap& GetWMap () { static WMap map; return map; } 
    }; 
 - также возврашалась невалидная ссылка, (вызов был инициирован из функции другого класса) несмотря на то что статическая переменная спрятаная в функцию  - однако перенос тела функции в .cpp исправил ситуацию.

Обе описанные ситуации были получены на компиляторе MinGW (других не пробовал)  
но установленные на разных компах давали разные результаты (скачивались с одного и того же сайта но в разное время - так что вполне могут быть разные по обновлению)

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

     




Это сообщение отредактировал(а) mes - 17.6.2008, 11:47


--------------------
PM MAIL WWW   Вверх
Alek86
Дата 17.6.2008, 11:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

Репутация: нет
Всего: 25



Код

class W { 
     typedef  std::map<std::string, W*> WMap;
     static WMap& GetWMap () { static WMap map; return map; } 
    }; 


есди этот код был в ашнике, то можент быть, создавались 2 реализацции функции GetWMap, и, соответственно, 2 статические переменные?


--------------------
user posted image    user posted image
PM MAIL   Вверх
Lazin
Дата 17.6.2008, 12:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: нет
Всего: 154



я понял что имеет место что-то вроде этого  smile :
Код

class A
{
    B& get()
    {
        static B b;
        return b;
    }
};

namespace {
    A static_a;
}

class Form
{
    ...
    ~Form()
    {
        B& = static_a.get();
    }
};

Form form(...);

int main()
{
    .....
}

ошибка может возникнуть из-за того, что порядок создания переменных не определен, если сначала создан объект form, потом static_a, ну а потом static B b;, то удаляться они будут в обратном порядке..
PM MAIL Skype GTalk   Вверх
UnrealMan
Дата 17.6.2008, 12:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 722
Регистрация: 30.3.2006

Репутация: нет
Всего: 32



Цитата(mes @  17.6.2008,  11:36 Найти цитируемый пост)
Вопрос:  как тогда правильно использовать функции возврашаюшиее ссылки на статические обьекты, чтоб избежать такого непредсказуемого поведения

В программе, где не допускается undefined behavior (легко сказать smile). Не исключено, что источником проблем служит участок кода, который с виду никак не должен сказываться на этих статических объектах.

Цитата(Alek86 @  17.6.2008,  11:50 Найти цитируемый пост)
есди этот код был в ашнике, то можент быть, создавались 2 реализацции функции GetWMap, и, соответственно, 2 статические переменные? 

С какой стати?


PM MAIL   Вверх
mes
Дата 17.6.2008, 12:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



Цитата(Alek86 @  17.6.2008,  11:50 Найти цитируемый пост)
создавались 2 реализацции функции GetWMap, и, соответственно, 2 статические переменные? 

нет.. двух перемнных  не создавалось - возврашалась невалидная ссылка 


Цитата(Lazin @  17.6.2008,  12:08 Найти цитируемый пост)
я понял что имеет место что-то вроде этого 
Код

namespace {
    A static_a;
}
  

нет.. открытых ( не обернутых в функцию) не было

весь код выглядит примерно так:
Код


 // a.cpp
А& GetA () { static A a; return a; }  
//a.h
class A
{
   void  func() {} // пустая функция тоже провоцирует вылет
}
А& GetA () ;

//wchild.h

class WChild { 
     typedef  std::map<std::string, WChild*> WMap;
     static WMap& GetWMap () { static WMap map; return map; } 
  public:
     static WChild *  GetWChild (const std::string& name) { WMap::iterator it = GetWMap().find(name);
                                                                                             return (it!=GetWMap().end())? it->second : NULL;
                                                                                           } 
    }; 

// wform.cpp
void OnClose (..)
{
 GetA(). func (); // если вместо деструктора последний раз вызывать здесь , то вылета не происходит
}

WForm::WForm (..) : WFrame (..)
{
}

WForm::~WForm (..) 
{
   GetA(). func (); // вылетает (1й случай)
}

void WForm:: CreateChild (..)
{
   if (WChild::GetWChild(name)  // здесь вылетает по пункту 2.
       {..}
}




Добавлено @ 12:32
названния функций условны.. но места вызовов сохранены 

Это сообщение отредактировал(а) mes - 17.6.2008, 12:44


--------------------
PM MAIL WWW   Вверх
Alek86
Дата 17.6.2008, 12:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

Репутация: нет
Всего: 25



Цитата(UnrealMan @  17.6.2008,  12:29 Найти цитируемый пост)
С какой стати?

я только предположил, ибо не знаю
к примеру из-за того, что каждый cpp компилится в свой obj
а как поступает компилер, когда видит код одной и той же функции в 2х cpp (и видит ли вообще) я не знаю. а может это вообще проблемы линковщика, подставить один и тот же адрес в 2 obj при их обработке


--------------------
user posted image    user posted image
PM MAIL   Вверх
Lazin
Дата 17.6.2008, 12:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: нет
Всего: 154



Цитата(mes @  17.6.2008,  12:31 Найти цитируемый пост)
if (WChild::GetWChild(name)  // здесь вылетает по пункту 2.

возможно нет такого ключа... вот и вылетает 

может сделать WMap членом класса?
PM MAIL Skype GTalk   Вверх
UnrealMan
Дата 17.6.2008, 12:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 722
Регистрация: 30.3.2006

Репутация: нет
Всего: 32



Цитата(Alek86 @  17.6.2008,  12:35 Найти цитируемый пост)
а как поступает компилер, когда видит код одной и той же функции в 2х cpp (и видит ли вообще) я не знаю. а может это вообще проблемы линковщика, подставить один и тот же адрес в 2 obj при их обработке 

Это inline-функция, с ней должен разобраться линкер - он оставит только одну функцию, которая во всех единицах трансляции будет одной и той же. Но, в принципе, тут могут быть косяки, можно попробовать пересобрать весь проект.
PM MAIL   Вверх
Lazin
Дата 17.6.2008, 12:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: нет
Всего: 154



Цитата(mes @  17.6.2008,  12:31 Найти цитируемый пост)
WForm::~WForm (..) : WFrame (..)
{
   GetA(). func (); // вылетает (1й случай)
}

видимо вылитает при завершении программы, если да, то возможно из-за того, что статический объект
Цитата(mes @  17.6.2008,  12:31 Найти цитируемый пост)
А& GetA () { static A a; return a; }  

уже уничтожен...

в этом случае поможет синглтон...
PM MAIL Skype GTalk   Вверх
UnrealMan
Дата 17.6.2008, 12:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 722
Регистрация: 30.3.2006

Репутация: нет
Всего: 32



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

Добавлено @ 12:46
Цитата(Lazin @  17.6.2008,  12:44 Найти цитируемый пост)
в этом случае поможет синглтон... 

Не всякий синглтон одинаково полезен.

Это сообщение отредактировал(а) UnrealMan - 17.6.2008, 12:48
PM MAIL   Вверх
Lazin
Дата 17.6.2008, 12:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: нет
Всего: 154



Цитата(UnrealMan @  17.6.2008,  12:45 Найти цитируемый пост)
Не всякий синглтон одинаково полезен.

использование одной статической переменной в деструкторе другой статической переменной ни разу не полезно smile 
PM MAIL Skype GTalk   Вверх
mes
Дата 17.6.2008, 12:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



Цитата(Lazin @  17.6.2008,  12:44 Найти цитируемый пост)
А& GetA () { static A a; return a; }  


уже уничтожен...

в этом случае поможет синглтон... 


так в чем различие между  
Код

А& GetA () { static A a; return a; }  
и
class Singleton { 
public:
A& GetInstace ()  { static A a; return a; }  
};
 ?



--------------------
PM MAIL WWW   Вверх
Lazin
Дата 17.6.2008, 12:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: нет
Всего: 154



mes, поставь в деструктор класса A брейкпоинт и проверь, кто раньше удаляется...
PM MAIL Skype GTalk   Вверх
UnrealMan
Дата 17.6.2008, 12:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 722
Регистрация: 30.3.2006

Репутация: нет
Всего: 32



Цитата(Lazin @  17.6.2008,  12:50 Найти цитируемый пост)
использование одной статической переменной в деструкторе другой статической переменной ни разу не полезно 

У паттерна "синглтон" много реализаций. Синглтон Мейерса базируется на тех же статических переменных, и проблемы у него будут те же самые smile

Это сообщение отредактировал(а) UnrealMan - 17.6.2008, 12:56
PM MAIL   Вверх
mes
Дата 17.6.2008, 12:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



Цитата(Lazin @  17.6.2008,  12:50 Найти цитируемый пост)
использование одной статической переменной в деструкторе другой статической переменной ни разу не полезно   


само окно не является глобальным обэектом


--------------------
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | GNU toolchain | Следующая тема »


 




[ Время генерации скрипта: 0.0913 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.