Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Исключение Access violation при вызо dynamic_cast, Причина? Чем грозит? Как правильно? 
V
    Опции темы
ZVano
Дата 15.4.2011, 12:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Есть кусок кода, который в таймере проверяет живы ли формы, указатели на которые сохранены в списке.
Проверка при помощи 
Код

TForm * castResult = dynamic_cast<TForm*>(myFormP)
.
Если myFormP указывает на прибитую ранее форму, то возникает исключение:
Access violation at address 32AB2EA1 in module 'CC32100MT.DLL'. Read of address 00000017

Вопросы:
1. В чем причина исключения?

Я же не меняю данные, а просто пытаюсь узнать проходит ли приведение типов.
2. Чем грозит это исключение, если не побороть причину?
Сейчас dynamic_cast завернут в try ... catch. Работает. Но кто его знает чем это может обернуться...
3. Как правильно выполнять данную операцию?
Если применение dynamic_cast в этом случае недопустимо, то зачем же он вообще нужен. Хочю работаю, хочю не работаю.

Это сообщение отредактировал(а) ZVano - 15.4.2011, 12:09


--------------------
НЕ ФЛУДИМ. Пользуемся кнопками "+" или "-" для выражения своего отношения к теме или сообщению.
Гуглим "Как правильно задавать вопросы"
PM MAIL Skype   Вверх
borisbn
Дата 15.4.2011, 12:38 (ссылка) |   (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 18
Всего: 135



Цитата(ZVano @  15.4.2011,  12:04 Найти цитируемый пост)
1. В чем причина исключения?Я же не меняю данные, а просто пытаюсь узнать проходит ли приведение типов.

ты обращаешься по невалидному указателю. dynamic_cast лезет в виртуальную таблицу (myFormP->v_fptr), а т.к. myFormP указывает не пойми куда, то и брать оттуда данные нельзя

Цитата(ZVano @  15.4.2011,  12:04 Найти цитируемый пост)
Сейчас dynamic_cast завернут в try ... catch. Работает. Но кто его знает чем это может обернуться...

это не есть правильно, потому, что try ... catch должен ловить пользовательские исключения, а не исключения обращения к несуществующей памяти.

Цитата(ZVano @  15.4.2011,  12:04 Найти цитируемый пост)
Если применение dynamic_cast в этом случае недопустимо, то зачем же он вообще нужен

Наврное для других случаев... http://lmgtfy.com/?q=dynamic_cast&l=1

Как ты думаешь, может стоило задать вопрос: "Как мне правильно сделать проверку живы ли формы ?", приведя при этом код создания, удаления и добавления форм в список ?


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
ZVano
Дата 15.4.2011, 13:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(borisbn @  15.4.2011,  12:38 Найти цитируемый пост)
Как ты думаешь, может стоило задать вопрос: "Как мне правильно сделать проверку живы ли формы ?", приведя при этом код создания, удаления и добавления форм в список ?

Возможно, ты прав. Но мне хотелось разобраться в причинах.
Предварительный анализ показал, что нужно воспользоваться API
IsBadCodePtr -  Определяет, имеет ли процесс права чтения памяти по указанному адресу
IsBadReadPtr - Определет, имеет ли процесс права чтения памяти по указанному диапазону адресов.
IsBadStringPtr - Определяет, может ли процесс использовать переданный указатель как указатель на ANSI-строку (заканчивающуюся символом с кодом 0). 
Функция проверяет, имеет ли процесс доступ к фрагменту памяти, который начинается от заданного указателя, и длина которого определяется первым вхождением символа с кодом 0, но не больше заданного количества символов.
 IsBadWritePtr - Определет, имеет ли процесс права записи в память по указанному диапазону адресов.
IsBadHugeReadPtr
IsBadHugeWritePtr


Копаю дальше...

Этот код не работает. Срабатывает "Форма жива" несмотря на то, что она совсем-совсем дохлая.
Код

if ( //
  IsBadWritePtr(myFormP, sizeof(TForm)) // Проверяем можем ли писать в область памяти формы
  || IsBadReadPtr(myFormP, sizeof(TForm)) // Проверяем можем ли читать из области памяти формы
  || IsBadCodePtr((FARPROC)myFormP) // Проверяем, имеем ли мы право читать по адресу размещения формы
) {
  ShowMessage("Форма жива")
}
else{
  ShowMessage("Форма мертва")
}


Таким образом универсальный способ проверки валидности указателей на произвольные данные не найден. Поиск продолжается.



Неуниверсальный способ (для форм) такой:
Код

// Просканировать MDI-Child формы для обслуживания закладок
// Действия: создание недостающих закладок; обновление текста закладок; удаление закладок для недостающих окон
void TAppAdmin::TabsScan(void) {
    // throw Exception("Проверка перехватчика искдючений...");

    // Создаем несуществующие вкладки для окон MDIChild
    for (int cnrMdiChild = 0; cnrMdiChild < frmMain->MDIChildCount; cnrMdiChild++) {
        TForm * curMdiChild = frmMain->MDIChildren[cnrMdiChild];
        int tabIndex = frmMain->pagesForm->Tabs->IndexOfObject(curMdiChild);
        if (tabIndex < 0) {
            tabIndex = frmMain->pagesForm->Tabs->AddObject(curMdiChild->Caption, curMdiChild);
        }

        // Изменения таба
        frmMain->pagesForm->Tabs->Strings[tabIndex] = curMdiChild->Caption;
    }

    // Обратное действие - прибиваем закладки, для которых нет окон
    for (int cnrTabs = frmMain->pagesForm->Tabs->Count - 1; cnrTabs >= 0; cnrTabs--) {
        bool isTabClose = true;
    TObject * tabObject = frmMain->pagesForm->Tabs->Objects[cnrTabs];
    
    // Ищем указатель на форму в массиве формы-родителя
    for (int cnrComp = 0; cnrComp < frmMain->ComponentCount; cnrComp++) {
      TComponent * curComp = frmMain->Components[cnrComp];
      if (curComp == tabObject) {
        isTabClose = false;
        break;
      }
    }
    
        if (isTabClose) {
            TabClose(cnrTabs);
        }
    }

}

Код проверен и работает.
frmMain - главная форма с MDIChild окнами.
pagesForm - TTabControl в Objects которого хранятся указатели на MDIChild формы.
TabClose - пользовательский метод, закрывающий таб с указаным индексом.

Принцип работы в том, чтобы пробежаться по массиву Components формы в поисках указателя на форму.
Если нашли, значит форма живая.

Это сообщение отредактировал(а) ZVano - 15.4.2011, 15:58


--------------------
НЕ ФЛУДИМ. Пользуемся кнопками "+" или "-" для выражения своего отношения к теме или сообщению.
Гуглим "Как правильно задавать вопросы"
PM MAIL Skype   Вверх
borisbn
Дата 15.4.2011, 16:21 (ссылка) |   (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 18
Всего: 135



Цитата(ZVano @  15.4.2011,  13:13 Найти цитируемый пост)
Но мне хотелось разобраться в причинах.

Это, конечно, правильно и хорошо, но IMHO ты не туда смотришь...
причину я тебе рассказал, а вот обходить её "слева и справа" неправильно. Лучше сделать так, чтобы этой ситуации никогда не было, а именно после удаления формы занулить указатель и вместо dynamic_cast проверять указатель на 0.


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Dem_max
Дата 15.4.2011, 17:02 (ссылка)  | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

Репутация: 14
Всего: 39



Топикстартер наверное очередной дэльфист


--------------------
Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte")
PM MAIL   Вверх
ZVano
Дата 15.4.2011, 17:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(borisbn @  15.4.2011,  16:21 Найти цитируемый пост)
... после удаления формы занулить указатель и вместо dynamic_cast проверять указатель на 0

В обычных условиях это единственно верное решение.
В моих условиях (оболочка управления окнами) приходится идти на компромис. 
Компромис в том, что приходится выбирать:
1. либо создание\уничтожение форм через специальный менеджер окон
2. либо мостоянный мониторинг окон

У каждого варианта свои достоинства и недостатки.
Я выбрал 2й вариант и это мое IMXO. 

Цитата(Dem_max @  15.4.2011,  17:02 Найти цитируемый пост)
Топикстартер наверное очередной дэльфист

Так и есть.




--------------------
НЕ ФЛУДИМ. Пользуемся кнопками "+" или "-" для выражения своего отношения к теме или сообщению.
Гуглим "Как правильно задавать вопросы"
PM MAIL Skype   Вверх
Dem_max
Дата 15.4.2011, 17:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

Репутация: 14
Всего: 39



borisbn - ихмо тебе уже все сказал, добавить нечего.


--------------------
Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte")
PM MAIL   Вверх
borisbn
Дата 15.4.2011, 17:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 18
Всего: 135



Цитата(ZVano @  15.4.2011,  13:13 Найти цитируемый пост)
Принцип работы в том, чтобы пробежаться по массиву Components формы в поисках указателя на форму.

не проще повесить обработчик на событие закрытия окна/вкладки/да чего угодно, и там вызывать TabClose 


Цитата(Dem_max @  15.4.2011,  17:02 Найти цитируемый пост)
Топикстартер наверное очередной дэльфист

Плох, ессно, не сам дельфи, а то, что начинающие программисты переходя с дельфи на билдер, и увидев одинакого названные классы, методы и свойства, решают, что и действия с ними можно делать такие же, как в дельфи... ну и не особо помогает им отвратная реализация Object Pascal'я в билдере



--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
ZVano
Дата 15.4.2011, 18:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



[ЯУОТЕ]не проще повесить обработчик на событие закрытия окна/вкладки/да чего угодно, и там вызывать [/ЯУОТЕ]


В таком случае нужно будет придерживаться определенной схемы работы (работа через менеджер окон).
Этого мне совсем не хочется. Забыл где-то в обработчик вставить вызов определенного метода и получим висячие окна, либо закладки без окон.
Можете сказать "Сам дурак. Не нужно допускать ошибок..."
Отвечу "А нафига мне гемориться? Я исключил саму возможность ошибки. Это облегчило работу программистов, которые пользуются оболочкой."


Блин. Сам флуд развожу  :-Д  Если есть интерес, можем обсудить этот вопрос в отдельной теме.

PS: Всем спасибо за участие в теме.

Это сообщение отредактировал(а) ZVano - 15.4.2011, 18:37


--------------------
НЕ ФЛУДИМ. Пользуемся кнопками "+" или "-" для выражения своего отношения к теме или сообщению.
Гуглим "Как правильно задавать вопросы"
PM MAIL Skype   Вверх
xvr
Дата 18.4.2011, 12:58 (ссылка) |   (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 48
Всего: 223



Цитата(ZVano @  15.4.2011,  18:14 Найти цитируемый пост)
В таком случае нужно будет придерживаться определенной схемы работы (работа через менеджер окон).

Отнюдь. Вы пытаетесь проверять валидность определенного класса окон. Для этого достаточно, что бы валидностью себя озадачились сами окна.
Код

set<TForm*> active_forms;

// В конструктор ваших форм добавляете -
active_rorms.insert(this);

// А в деструктор -
active_forms.erase(this);

// Проверка валидности формы -
if (active_forms.count(<form ptr>)!=0) ... // Валидна

Хотя при таком подходе возможен сбой, если новая форма (созданная по new) ляжет на место старой (удаленной). Указатель на нее будет тем же, а вот <form ptr> может подразумеваться из 'прошлой жизни'  smile Это решается специальным полем в форме, со сквозным номером (ну и сохранение его вместе с <form ptr>)


PM MAIL   Вверх
ZVano
Дата 18.4.2011, 15:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Обсуждение плюсов\минусов различных подходов предлагаю обсуждать тут


--------------------
НЕ ФЛУДИМ. Пользуемся кнопками "+" или "-" для выражения своего отношения к теме или сообщению.
Гуглим "Как правильно задавать вопросы"
PM MAIL Skype   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++ Builder"
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по С++ Builder обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Настоятельно рекомендуем заглянуть в DRKB (Delphi Russian Knowledge Base) - крупнейший в рунете сборник материалов по Дельфи


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

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


 




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


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

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