Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Обработка исключения, может ли что-нибудь испортить 
V
    Опции темы
Peter
Дата 8.1.2006, 22:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Конкретно дело обстоит так. Многооконное приложение; каждое дочернее окно - объект класса <КлассДокумента>. Когда дочернее окно открыто, в объекте этого класса может выполняться некоторая операция (функция F вызывается по таймеру). В функции F используется переменная x - член класса <КлассДокумента>, имеющий тип "указатель на структуру S". В конструкторе <КлассДокумента>
Код
x = new S;

в деструкторе
Код
x = delete S;

Рассмотрим следующую ситуацию (которая наблюдалась в работе программы): в момент выполнения функции F пользователь закрывает окно. В деструкторе уничтожается объект, на который указывает x, и в то же самое время x используется в F. Если ничего не предпринимать, то программа вылетает.
Может ли что-нибудь испортиться, если я заключу тело F в
Код
try{<тело>}catch(...){}

?????????????? Не повредится ли, например, стэк?


--------------------
всё, что делаете, делайте от души, как для Господа (Послание апостола Павла колоссянам, 3:23).
PM MAIL WWW   Вверх
Fedor
Дата 8.1.2006, 22:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Днепрянин
****


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

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



Цитата(Peter @ 8.1.2006, 22:24 Найти цитируемый пост)

в момент выполнения функции F пользователь закрывает окно

может, я туплю, но разве такое может быть? события разве не поочереди выполняются? т.е. сначала до конца до работает функция, а потом только вызовется деструктор? Буду рад, если поправите меня. smile


--------------------
Мы - Днепряне. Мы всех сильней.
PM ICQ   Вверх
Mayk
Дата 8.1.2006, 23:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


Профиль
Группа: Участник
Сообщений: 2616
Регистрация: 22.5.2005
Где: за границей разум а

Репутация: 45
Всего: 134



А может стоит воспользваться чем-нибудь типа shared_ptr, или еще каким имеющимся классом для
подсчета ссылок? В крайнем случае накатать самому.

Цитата(Fedor @ 9.1.2006, 02:31 Найти цитируемый пост)

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

Если приложение многопоточное, и деструктор вызовется не из того потока, в котором выполняется F, то может прийти Большой Ой.
Добавлено @ 23:12
Цитата(Peter @ 9.1.2006, 02:24 Найти цитируемый пост)

1:try{<тело>}catch(...){}

А что нам это даст?

Код

int main()
{
  int *s = new s[10];delete[] s;
  try{s[3]=3;}catch(...){abort();}
}

завершается нормально


--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
chipset
Дата 8.1.2006, 23:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 4071
Регистрация: 11.1.2003
Где: Seattle, US

Репутация: 27
Всего: 165



Курим MSDN на тему синхронизации потоков или используем метод подсчета ссылок как правильно подметил Mayk smile


--------------------
Цитата(Jimi Hendrix)
Well, I stand up next to a mountain
And I chop it down with the edge of my hand
PM MAIL WWW   Вверх
Peter
Дата 9.1.2006, 12:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(Mayk @ 8.1.2006, 23:07 Найти цитируемый пост)
Код
try{<тело>}catch(...){}

А что нам это даст?
Код
int main()    
{    
  int *s = new s[10];delete[] s;    
  try{s[3]=3;}catch(...){abort();}    
}

завершается нормально

Первое нам даст то, что при выполнении F программа не вылетит.
Второе не подходит (наверно, имелось в виду
Код
int *s = new int[10];
), поскольку надо, чтобы корректно закрылось одно дочернее окно, а не все приложение завершило работу.

Синхронизация потоков, конечно, это хорошо, но слишком долго, и в ней нет необходимости, поскольку результат работы функции F пользователя уже не интересует. А поставить try-catch - это дело нескольких секунд. Вопрос лишь в том, не может ли быть от этого побочных эффектов?


--------------------
всё, что делаете, делайте от души, как для Господа (Послание апостола Павла колоссянам, 3:23).
PM MAIL WWW   Вверх
Mayk
Дата 9.1.2006, 16:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


Профиль
Группа: Участник
Сообщений: 2616
Регистрация: 22.5.2005
Где: за границей разум а

Репутация: 45
Всего: 134



Цитата(Peter @ 9.1.2006, 16:49 Найти цитируемый пост)

int *s = new int[10];

Ага

Цитата(Peter @ 9.1.2006, 16:49 Найти цитируемый пост)

Первое нам даст то, что при выполнении F программа не вылетит.

Да ну? Вы СЛИШКОМ высокого мнения об исключениях. В мной указаном примере произошла запись в уже удаленный s. И исключения не возникло(откуда? кто будет кидать исключение? система? а как она узнает что память освобождена?).
Точно так же оно не возникнет если в Вашей программе удалить объект из другого потока:
Цитата(Peter @ 9.1.2006, 02:24 Найти цитируемый пост)

Рассмотрим следующую ситуацию (которая наблюдалась в работе программы): в момент выполнения функции F пользователь закрывает окно. В деструкторе уничтожается объект, на который указывает x, и в то же самое время x используется в F.


Исключения не связаны с синхронизацией потоков.
Исключения не возникают, когда происходит запись не туда куда надо.
Исключения не вознакают, когда происходит чтения из разрушенного/(что еще хуже) полуразрушенного объекта. Чтобы поймать исключения, его нужно кинуть
Исключение не может быть поймано, если оно не брошено.


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

struct S{
 bool doNotDeleteMe
 ...не важно...
};

void F(S*x){
  x->doNotDeleteMe = true;
  ..не важно..
  x->doNotDeleteMe = false;
}
...
Window::~Window(){
  volatile int& i = const_cast<volatile int&>(s->doNotDeleteMe); 
  while(i); //ждём когда можно удалить
  delete s;
  ...что-то там...
}

И наблюдаем за крахом, в тот момент, когда один поток начнет выполнять F,
прервется до x->doNotDeleteMe = true;, передаст управление другому потоку, который благополучно разрушит x.
ОЙ.

Цитата(Peter @ 9.1.2006, 16:49 Найти цитируемый пост)

Синхронизация потоков, конечно, это хорошо, но слишком долго, и в ней нет необходимости, поскольку результат работы функции F пользователя уже не интересует.

В ней (или в альтернативе из подсчёта ссылок => позднего удаления) есть необходимость. Иначе программа умрёт.



--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
Earnest
Дата 9.1.2006, 17:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Синхронизация и подсчет ссылок - это не альтернативы, а Необходимые Вещи (причем обе сразу). Впрочем, вместо подсчета ссылок можно придумать какой-нибудь другой механизм управления владением и временем жизни. Но подсчет ссылок - наиболее простой и естественный в данном случае, ИМХО.
Но если есть разные потоки, работающие с одними и теми же данными, в синхронизации всегда есть необходимость!
В данном случае это касается возможной реализации shared_ptr - придется позаботиться о том, чтобы все его методы были потокобезопасны (скажем, инкремент-декремент числа ссылок должен быть атомарным, и т.д.).
Иначе твоя программа будет работать или валиться в зависимости от погоды на Галапагосских островах.


--------------------
...
PM   Вверх
Peter
Дата 9.1.2006, 21:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(Mayk @ 9.1.2006, 16:32 Найти цитируемый пост)
Исключение не может быть поймано, если оно не брошено.

Специально для проверки ставил
Код
catch(...){<message-box>}

и сообщение в message-box было благополучно показано, а программа продолжала работать.
Цитата(Mayk @ 9.1.2006, 16:32 Найти цитируемый пост)
В ней (или в альтернативе из подсчёта ссылок => позднего удаления) есть необходимость. Иначе программа умрёт.

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

Это сообщение отредактировал(а) Peter - 9.1.2006, 22:56


--------------------
всё, что делаете, делайте от души, как для Господа (Послание апостола Павла колоссянам, 3:23).
PM MAIL WWW   Вверх
threef
Дата 9.1.2006, 21:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 375
Регистрация: 27.10.2005
Где: Запорожье

Репутация: 9
Всего: 10



Стек не повредится, x указывает на кучу.
Как у тебя происходит управление функцией F , вернее, таймером ? Если таймер привязан к существовании этого дочернего окна, то просто убей его в OnDestroy этого окна. Если у тебя функция по таймеру очень медленная, ( в процессе ее однократного выполнения пользователь может открыть и закрыть окно) , то все равно в однопотоковом приложении этого просто не произойдет smile По определению в одном потоке два сообщения одновременно не обрабатывается, второе ждет себе в очереди. Поэтому, при входе в функцию F проверь x!=NULL, а при удалении окна

Код

delete x;
x=NULL;


Примечание: при использовании многопоточности действительно могут возникнуть всякие ОЙ, этим методом пользоваться нельзя.
PM MAIL   Вверх
Peter
Дата 9.1.2006, 23:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Приложение многопоточное.
Цитата(threef @ 9.1.2006, 21:19 Найти цитируемый пост)
Стек не повредится, x указывает на кучу.
Спасибо, я и хотел найти подтверждение, что все будет нормально. Вопрос закрыт.


--------------------
всё, что делаете, делайте от души, как для Господа (Послание апостола Павла колоссянам, 3:23).
PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




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


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

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