Добро пожаловать! Это — архивная версия форумов на «Хакер.Ru». Она работает в режиме read-only.
 

Работа с памятью

Пользователи, просматривающие топик: none

Зашли как: Guest
Все форумы >> [Компилируемые языки] >> Работа с памятью
Имя
Сообщение << Старые топики   Новые топики >>
Работа с памятью - 2007-09-27 10:00:25.786666   
mindgen

Сообщений: 12
Оценки: 0
Присоединился: 2007-09-27 09:32:38.196666
Есть какая-то ссылка, пусть для определенности: long * a;
с ней поработали и вызвали delete a;
Но не присвоили NULL. Таким образом память уже освободилась, а ссылка (адрес) остался.
Внимание вопрос:
Каким образом можно узнать, что память уже освобождена если в "<type> * a" не было присвоено NULL.

Другими словами: "Как избежать AV?"
Post #: 1
RE: Работа с памятью - 2007-09-27 11:44:33.366666   
JD_WERT

Сообщений: 117
Оценки: 0
Присоединился: 2007-07-12 06:59:16.613333
quote:

Как избежать

Не делать так:
quote:

с ней поработали и вызвали delete a;
Но не присвоили NULL

Ну, или сделать так:
#define DELETE(x) delete x; x = NULL;
После чего вызывать DELETE(a) а не delete a
Post #: 2
RE: Работа с памятью - 2007-09-27 11:47:24.620000   
JD_WERT

Сообщений: 117
Оценки: 0
Присоединился: 2007-07-12 06:59:16.613333
А еще можно попробовать выделять память через VirtualAlloc, освобождать - VirtualFree, а потом проверять - IsBadReadPtr/isBadWritePtr
Post #: 3
RE: Работа с памятью - 2007-09-27 12:34:34.630000   
mindgen

Сообщений: 12
Оценки: 0
Присоединился: 2007-09-27 09:32:38.196666
Спасибо!
Такой уж код достался. (
Что в реализации интерфейса, в каждый экземпляр пихается ссылка на один и тот же экземпляр класса…
При вызова (…)->Release у инферфейса он удаляет объект из памяти, а другие-то интерфейсы об этом не знают… (
Вот и валится AV. А переделывать все-не представляется возможным…
Post #: 4
RE: Работа с памятью - 2007-09-27 13:14:12.286666   
Absurd

Сообщений: 335
Оценки: 0
Присоединился: 2007-08-24 13:14:11.566666
quote:

Что в реализации интерфейса, в каждый экземпляр пихается ссылка на один и тот же экземпляр класса…
При вызова (…)-&gt;Release у инферфейса он удаляет объект из памяти, а другие-то интерфейсы об этом не знают… (

В СОМ если ты сохраняешь куда-то полученный интерфейс ты должен ->AddRef() сделать вообще-то. Или в этом проекте не так?

Post #: 5
RE: Работа с памятью - 2007-09-27 13:20:58.903333   
mindgen

Сообщений: 12
Оценки: 0
Присоединился: 2007-09-27 09:32:38.196666
В том -то и дело, что это не COM-интерфейс, а обычный класс ссылка на который в качестве переменной объявленна в реализации COM'a.
Post #: 6
RE: Работа с памятью - 2007-09-27 13:27:31.260000   
Absurd

Сообщений: 335
Оценки: 0
Присоединился: 2007-08-24 13:14:11.566666
А что за библиотека используется? MFC или ATL? Я правильно понял что тебе надо удалять объект перед тем как COM объект будет удален?
Post #: 7
RE: Работа с памятью - 2007-09-27 14:30:24.980000   
mindgen

Сообщений: 12
Оценки: 0
Присоединился: 2007-09-27 09:32:38.196666
Используется ATL.
Допустим есть 2 экземпляра интерфейса:
IExamplePtr Ex1, Ex2;
В реализации IExamplePtr есть ссылка на класс Test(class Test {…}).
Для инициализации IExamplePtr нужен класс Test(Init(Test * Val):
Т.к. Ex2 просто копия, то в Init отдается сслыка из Ex1:
Ex2 = Ex1->Copy();
Где в Copy происходит следующее:
… Copy()…
{

Ex2->Init(Ex1->obj); // где obj есть Test *

}

При вызове методо IExamplePtr дергаются методы класса Test.

Допустим, поработали с Ex1 и релизим его. В деструкторы удаляем из памяти класс Test.
Таким образом память по адресу, где раньше находился экземпляр класса Test, освобождена, но т.к. мы ссылку на этот класс отдавали в Init для Ex2, то Ex2 не знает, что память уже освободилась.

Затем релизится Ex2, и в нем опять вызывается delete для Test, который уже был освобожден в Ex1.
Происходит AV.
Вот как узнать в деструкторе у IExamplePtr освободили уже память для класса Test или нет.
Проверка на NULL естесвенно неп сработате,т.к. в Ex2 адрес на Test остался.
Post #: 8
RE: Работа с памятью - 2007-09-27 15:00:00.700000   
JD_WERT

Сообщений: 117
Оценки: 0
Присоединился: 2007-07-12 06:59:16.613333
А если сделать метод типа OpenObject() который будет возвращать указатель на ex1, а также увеличивать внутренний счетчик. А после работы с объектом вызывать ReleaseObject() которая будет уменьшать счетчик, и если он достиг нуля, удалять объект?
Post #: 9
RE: Работа с памятью - 2007-09-27 15:12:50.046666   
Absurd

Сообщений: 335
Оценки: 0
Присоединился: 2007-08-24 13:14:11.566666
Не, так не пойдет. Считай параллельно ссылки для этого указателя и удаляй только когда он обнулится. Можешь boost::shared_ptr использовать.
Post #: 10
RE: Работа с памятью - 2007-09-27 15:12:51.920000   
mindgen

Сообщений: 12
Оценки: 0
Присоединился: 2007-09-27 09:32:38.196666
Дело не в интерфейсе, там делаются все нужные AddRef'ы.
Дело в адресе класса, который содержится в 2-х независимых интефрейсах.
Post #: 11
RE: Работа с памятью - 2007-09-27 15:24:58.526666   
mindgen

Сообщений: 12
Оценки: 0
Присоединился: 2007-09-27 09:32:38.196666
quote:

boost::shared_ptr

не могу найти его в MSDN?
можно поподробнее?
Post #: 12
RE: Работа с памятью - 2007-09-27 15:25:57.016666   
JD_WERT

Сообщений: 117
Оценки: 0
Присоединился: 2007-07-12 06:59:16.613333
Но ex2 не будет же использовать указатель на ex1 после того, как сам его закрыл?
Post #: 13
RE: Работа с памятью - 2007-09-27 15:32:38.663333   
mindgen

Сообщений: 12
Оценки: 0
Присоединился: 2007-09-27 09:32:38.196666
Не, ты не понял.
Ex1 и Ex2 не знают друг о друге ничего. Их объединяет лишь одинаковый адрес на класс Test.
Post #: 14
RE: Работа с памятью - 2007-09-27 15:40:06.760000   
JD_WERT

Сообщений: 117
Оценки: 0
Присоединился: 2007-07-12 06:59:16.613333
Я понял это так:
class IExample { ITest* ptr; public: IExample(ITest* p): ptr(p) { } Foo() { ptr-&gt;Bar(); } Destroy() { delete ptr; } }; main() { ITest* t = new ITest; IExample ex1(t); IExample ex2(t); ex1.Destroy(); ex2.Foo(); ex2.Destory(); }
Post #: 15
RE: Работа с памятью - 2007-09-27 15:56:10.170000   
mindgen

Сообщений: 12
Оценки: 0
Присоединился: 2007-09-27 09:32:38.196666
Вообщем-то так тоже можно интерпретировать…. :)
Вот как избавиться от AV на строчке ex2.Foo();
Post #: 16
RE: Работа с памятью - 2007-09-27 16:01:16.790000   
JD_WERT

Сообщений: 117
Оценки: 0
Присоединился: 2007-07-12 06:59:16.613333
class ITest { int refs = 0; ITest* AddRef() { refs++; return this; } void Drop() { if (!--refs) delete this; // объект-камикадзе } }; class IExample { ITest* ptr; public: IExample(ITest* p) { ptr = p-&gt;AddRef(); } Foo() { ptr-&gt;Bar(); } Destroy() { ptr-&gt;Drop(); } }; main() { ITest* t = new ITest; IExample ex1(t); IExample ex2(t); ex1.Destroy(); ex2.Foo(); ex2.Destory(); }
Post #: 17
RE: Работа с памятью - 2007-09-27 16:39:22.846666   
mindgen

Сообщений: 12
Оценки: 0
Присоединился: 2007-09-27 09:32:38.196666
Собственно это есть аналог работы интерфейсов(счетчик ссылок на объект)
У меня так сделать не получится, слишко м много кода придется перехачить. Попробуй сделать класс аналогичный CAutoPtr, только для своей задачи.
Post #: 18
RE: Работа с памятью - 2007-09-28 13:14:21.510000   
mindgen

Сообщений: 12
Оценки: 0
Присоединился: 2007-09-27 09:32:38.196666
Так делать тоже не выход,в моем случае. Буду делать глобальную мапу. Где ключ-адрес, азначение кол-во ссылок на адрес. Извращенство конечно, а что делать… )
Post #: 19
Страниц:  [1]
Все форумы >> [Компилируемые языки] >> Работа с памятью







Связаться:
Вопросы по сайту / xakep@glc.ru

Предупреждение: использование полученных знаний в противозаконных целях преследуется по закону.