Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проблемы при чтении куска разрушенного объекта, звучит странно, а что делать 
V
    Опции темы
dizzy1984
Дата 18.12.2009, 15:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Ситуация такова.
Моя dll получает объект от основной программы, какое-то время работает с ним. Затем объект уничтожается основной программой.
Но в dll-ке есть баг, и dll-ка читает одно поле этого убитого объекта. av не происходит, но поведение программы изменяется - через какое-то время она выводит одиночное окошко с информативным сообщением. Смысл сообщения специфичен для предметной области и не относится к работе с памятью. И все.
Мне принципиально неясно как _чтение_ пусть даже разрушенных данных может быть зарегистрировано программой.
PM MAIL   Вверх
djamshud
Дата 18.12.2009, 15:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Пердупержденный
***


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

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



Программой - никак (если самому не делать костылей вокруг new/delete), а вот операционкой - вполне, ибо память не только "разрушается", но и освобождается.


--------------------
'Cuz I never walk away from what I know is right
Alice Cooper - Freedom
PM   Вверх
586
Дата 18.12.2009, 16:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



dizzy1984, с таким подходом, тебе технологию COM надо юзать, либо писать что-то аналогичное.






Это сообщение отредактировал(а) 586 - 18.12.2009, 16:01
PM   Вверх
dizzy1984
Дата 18.12.2009, 16:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



586, все правильно, это com-объект, но ты на вопрос-то ответь.
Как может быть реакция на чтение данных в адресном пространстве.
PM MAIL   Вверх
586
Дата 18.12.2009, 16:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Предлагаю не проверять память, а просто по другому работать с объектом.
Как-нибудь так:

.exe
Код
pObject->AddRef();
DllFunction(pObject);
//...
//...
pObject->Kill();
pObject->Release();

.dll
Код
void DllFunction(IObject *pObject)
{
    //...
    if(pObject->IsKilled())
    {
        pObject->Release();
        return;
    }
    //...
    pObject->Release();
}

PM   Вверх
GremlinProg
Дата 18.12.2009, 16:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(dizzy1984 @  18.12.2009,  18:05 Найти цитируемый пост)
Как может быть реакция на чтение данных в адресном пространстве.

а что, собственно, удивляет?

пока память действительно не будет освобождена  кучей, все данные,
пусть даже и "мусорные", продолжают выполнять свою роль:
если это VMT, то она по прежнему указывает на методы, и методы по прежнему можно вызывать,

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


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
dizzy1984
Дата 19.12.2009, 10:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(GremlinProg @  18.12.2009,  18:16 Найти цитируемый пост)
а что, собственно, удивляет?

Хмм.
Может я как-то не так говорю, моя программа не осуществляет запись в адресное пространство основной программы, она осуществляет чтение данных из ее адресного пространства.
Вот минимальный код, приводящий к проблеме.
Пардон, на дельфи
Код

function Document3dEvent.Rebuild : WordBool;
var
i1 : reference;
begin
i1 := iDoc3D.reference;
Result := true;
end;

где idoc3d интерфейсная ссылка
Код

iDoc3D : ksDocument3D;
//..
ksDocument3D = dispinterface
    ['{111CEFE1-A0A7-11D6-95CE-00C0262D30E3}']
    property reference: Integer dispid 39;
    //..
  end;



Поставил брейкпоинт на данные - в строке чтения значения осуществляется запись в тело объекта со смещением 4 байта smile
Сначала вызывается дельфовая DispCallByID, затем DispCall, затем неименованная функция библиотеки MFC42u.dll, которая и осуществляет запись smile. После длительных раздумий решил, что COM-среда рассматривает кусок COM-объекта как область памяти для некоторых своих переменных и даже вызов немодифицирующей объект функции приводит к изменения в этой области памяти.

Это все объясняет, а как я говорил вначале в случае записи этого бы не проихошло
PM MAIL   Вверх
GremlinProg
Дата 19.12.2009, 11:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



вообще-то, конкретно о записи я слышу в первый раз, надо стараться просто яснее выражать свои мысли
Цитата(dizzy1984 @  19.12.2009,  12:32 Найти цитируемый пост)
в строке чтения значения осуществляется запись в тело объекта со смещением 4 байта

сильно сомневаюсь, что это делает "COM-среда", т.к. эта среда, если мы об одном и том же говорим, 
заканчивается сразу за вызовом IDispatch::invoke

конечно, за пределами 4 первх байт объекта могут начинаться непосредственно данные "черного ящика",
запись туда вполне могла бы делать "отлаживаемая среда",
т.е. реальный класс COM объекта вполне может наследоваться от какого-то класса MFC-шного COM объекта,
типа "трейсера" (tracer) во время отладки, и коннечно данные этого трейсера будут расположены ранее в пределах объекта

в принципе, да, если приравнять этого предка к "COM-среде", то ход мыслей верный,
т.е. да - "СOM-среда рассматривает кусок COM-объекта как область памяти для некоторых своих переменных",
т.к. этот кусок объекта есть собственность самой этой среды, она может делать с ним что хочет, хоть писать во время чтения )


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
xvr
Дата 19.12.2009, 12:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(dizzy1984 @ 19.12.2009,  10:32)
Может я как-то не так говорю, моя программа не осуществляет запись в адресное пространство основной программы, она осуществляет чтение данных из ее адресного пространства.

Не то и не другое  smile 
Цитата

Вот минимальный код, приводящий к проблеме.
Пардон, на дельфи
Код

function Document3dEvent.Rebuild : WordBool;
var
i1 : reference;
begin
i1 := iDoc3D.reference;
Result := true;
end;

где idoc3d интерфейсная ссылка
Твой программа осуществляет ВЫЗОВ виртуального метода от уничтоженного объекта.

Все общение с ЛЮБЫМ COM объектом (а уж тем более с IDispatch) осуществляется ТОЛЬКО через vtbl, так уж COM устроен  smile 
А уж метод (даже если это реализация чтения проперти) может сделать что угодно, например проверить валидность объекта и даже обновить в нем что захочет  smile 

PM MAIL   Вверх
dizzy1984
Дата 19.12.2009, 19:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Это все понятно.
Я смотрел реализацию метода ksDocument3D:Reference (точнее, все вызовы dll-ки, где реализован функционал ksDocument3D расположенные в строке
Код

i1 := iDoc3D.reference;

)
Они не модифицируют объект. 
Подумай сам - метод, возвращающий целое число модифицирует объект?? Где интуитивная понятность? Где прозрачность кода?? Такого просто не может быть.
GremlinProg, предложил интересное объяснение. Если я правильно его понял, то есть MFC-класс, потомок IDispatch, который переопределяет метод invoke. ksDocument3D (к слову сказать, реализация ksDocument3d собиралась компилятором идущим с visual studio 6.0, так что есть все шансы что использовалась mfc) использует его. И это переопределение пишется в свой кусок ksDocument3D в случае чтения данных. Странно, непонятно, но оно это делает. Зачем надо хранить информацию о том, что вот мол, меня прочитали. 
Дальше - больше. Com-объект сидел где-то в хипе основной программы. Умер. Старательная обертка idispatch зафиксировала чтение данных. Записала в труп. Прошла новая операция с хипом. Хип проверил целостность блоков. Обнаружил запись. Дальши либо отказался сотрудничать, либо забацал исключение. Отсюда вывод информационного сообщения.
По большому счету все это укладывается в канву - не работай с умершим объектом. Просто мне было интересно.
PM MAIL   Вверх
GremlinProg
Дата 19.12.2009, 21:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(dizzy1984 @  19.12.2009,  21:41 Найти цитируемый пост)
Зачем надо хранить информацию о том, что вот мол, меня прочитали

может что-то типо автодокументации,
т.е. после запуска A, нужно выполнить B, потом прочитать C, чтобы выполнить D

стейт-машина, по типу:
Код

#ifdef _STRSAFE_H_INCLUDED_
#error Need to include strsafe.h after tchar.h
#endif



--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
xvr
Дата 20.12.2009, 12:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(dizzy1984 @ 19.12.2009,  19:41)
Я смотрел реализацию метода ksDocument3D:Reference (точнее, все вызовы dll-ки, где реализован функционал ksDocument3D расположенные в строке
Код

i1 := iDoc3D.reference;

)
Они не модифицируют объект. 

Проблема в том, что мог быть вызван уже не ksDocument3D:Reference  smile Т.к. вызов идет через vtbl, а указатель на нее хранится в уже освобожденной части хипа, то кто то мог после удаления объекта (но до выхова ksDocument3D:Reference) заказать память, получить кусок памяти, где раньше был объект и переписать то место, где был указатель на vtbl.
Цитата

Подумай сам - метод, возвращающий целое число модифицирует объект?? Где интуитивная понятность? Где прозрачность кода?? Такого просто не может быть.
GremlinProg предложил такую реализацию, ты же сам писал:
Цитата

GremlinProg, предложил интересное объяснение.  Если я правильно его понял, то есть MFC-класс, потомок IDispatch, ...


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


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(xvr @  20.12.2009,  14:26 Найти цитируемый пост)
Проблема в том, что мог быть вызван уже не ksDocument3D:Reference   Т.к. вызов идет через vtbl, а указатель на нее хранится в уже освобожденной части хипа, то кто то мог после удаления объекта (но до выхова ksDocument3D:Reference) заказать память, получить кусок памяти, где раньше был объект и переписать то место, где был указатель на vtbl.

да, вполне возможно,
и раз уж dizzy1984, так глубоко залез в это,
то может проверить по одинаковым ли адресам прыгает программа до и после Release,
т.е. по крайней мере, посмотреть куда прыгает до...

я вообще не вижу ничего криминального в том, что при чтении, и даже из константы ( если вдруг ) кто-то что-то в нее пишет,
в конце-концов, такое поведение легализовано в C++, на уровне модификатора mutable,
а в Pascal/Delphi (ранних версий, по крайней мере) этому даже внимание не уделяется

на то они и свойства, чтобы скрывать сложную и/или неоднозначную логику доступа к полю


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


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

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


 




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


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

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