Работа с памятью
Пользователи, просматривающие топик: 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?"
|
|
|
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
|
|
|
RE: Работа с памятью - 2007-09-27 11:47:24.620000
|
|
|
JD_WERT
Сообщений: 117
Оценки: 0
Присоединился: 2007-07-12 06:59:16.613333
|
А еще можно попробовать выделять память через VirtualAlloc, освобождать - VirtualFree, а потом проверять - IsBadReadPtr/isBadWritePtr
|
|
|
RE: Работа с памятью - 2007-09-27 12:34:34.630000
|
|
|
mindgen
Сообщений: 12
Оценки: 0
Присоединился: 2007-09-27 09:32:38.196666
|
Спасибо! Такой уж код достался. ( Что в реализации интерфейса, в каждый экземпляр пихается ссылка на один и тот же экземпляр класса… При вызова (…)->Release у инферфейса он удаляет объект из памяти, а другие-то интерфейсы об этом не знают… ( Вот и валится AV. А переделывать все-не представляется возможным…
|
|
|
RE: Работа с памятью - 2007-09-27 13:14:12.286666
|
|
|
Absurd
Сообщений: 335
Оценки: 0
Присоединился: 2007-08-24 13:14:11.566666
|
quote:
Что в реализации интерфейса, в каждый экземпляр пихается ссылка на один и тот же экземпляр класса… При вызова (…)->Release у инферфейса он удаляет объект из памяти, а другие-то интерфейсы об этом не знают… ( В СОМ если ты сохраняешь куда-то полученный интерфейс ты должен ->AddRef() сделать вообще-то. Или в этом проекте не так?
|
|
|
RE: Работа с памятью - 2007-09-27 13:20:58.903333
|
|
|
mindgen
Сообщений: 12
Оценки: 0
Присоединился: 2007-09-27 09:32:38.196666
|
В том -то и дело, что это не COM-интерфейс, а обычный класс ссылка на который в качестве переменной объявленна в реализации COM'a.
|
|
|
RE: Работа с памятью - 2007-09-27 13:27:31.260000
|
|
|
Absurd
Сообщений: 335
Оценки: 0
Присоединился: 2007-08-24 13:14:11.566666
|
А что за библиотека используется? MFC или ATL? Я правильно понял что тебе надо удалять объект перед тем как COM объект будет удален?
|
|
|
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 остался.
|
|
|
RE: Работа с памятью - 2007-09-27 15:00:00.700000
|
|
|
JD_WERT
Сообщений: 117
Оценки: 0
Присоединился: 2007-07-12 06:59:16.613333
|
А если сделать метод типа OpenObject() который будет возвращать указатель на ex1, а также увеличивать внутренний счетчик. А после работы с объектом вызывать ReleaseObject() которая будет уменьшать счетчик, и если он достиг нуля, удалять объект?
|
|
|
RE: Работа с памятью - 2007-09-27 15:12:50.046666
|
|
|
Absurd
Сообщений: 335
Оценки: 0
Присоединился: 2007-08-24 13:14:11.566666
|
Не, так не пойдет. Считай параллельно ссылки для этого указателя и удаляй только когда он обнулится. Можешь boost::shared_ptr использовать.
|
|
|
RE: Работа с памятью - 2007-09-27 15:12:51.920000
|
|
|
mindgen
Сообщений: 12
Оценки: 0
Присоединился: 2007-09-27 09:32:38.196666
|
Дело не в интерфейсе, там делаются все нужные AddRef'ы. Дело в адресе класса, который содержится в 2-х независимых интефрейсах.
|
|
|
RE: Работа с памятью - 2007-09-27 15:24:58.526666
|
|
|
mindgen
Сообщений: 12
Оценки: 0
Присоединился: 2007-09-27 09:32:38.196666
|
quote:
boost::shared_ptr не могу найти его в MSDN? можно поподробнее?
|
|
|
RE: Работа с памятью - 2007-09-27 15:25:57.016666
|
|
|
JD_WERT
Сообщений: 117
Оценки: 0
Присоединился: 2007-07-12 06:59:16.613333
|
Но ex2 не будет же использовать указатель на ex1 после того, как сам его закрыл?
|
|
|
RE: Работа с памятью - 2007-09-27 15:32:38.663333
|
|
|
mindgen
Сообщений: 12
Оценки: 0
Присоединился: 2007-09-27 09:32:38.196666
|
Не, ты не понял. Ex1 и Ex2 не знают друг о друге ничего. Их объединяет лишь одинаковый адрес на класс Test.
|
|
|
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->Bar();
}
Destroy()
{
delete ptr;
}
};
main()
{
ITest* t = new ITest;
IExample ex1(t);
IExample ex2(t);
ex1.Destroy();
ex2.Foo();
ex2.Destory();
}
|
|
|
RE: Работа с памятью - 2007-09-27 15:56:10.170000
|
|
|
mindgen
Сообщений: 12
Оценки: 0
Присоединился: 2007-09-27 09:32:38.196666
|
Вообщем-то так тоже можно интерпретировать…. :) Вот как избавиться от AV на строчке ex2.Foo();
|
|
|
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->AddRef();
}
Foo()
{
ptr->Bar();
}
Destroy()
{
ptr->Drop();
}
};
main()
{
ITest* t = new ITest;
IExample ex1(t);
IExample ex2(t);
ex1.Destroy();
ex2.Foo();
ex2.Destory();
}
|
|
|
RE: Работа с памятью - 2007-09-27 16:39:22.846666
|
|
|
mindgen
Сообщений: 12
Оценки: 0
Присоединился: 2007-09-27 09:32:38.196666
|
Собственно это есть аналог работы интерфейсов(счетчик ссылок на объект) У меня так сделать не получится, слишко м много кода придется перехачить. Попробуй сделать класс аналогичный CAutoPtr, только для своей задачи.
|
|
|
RE: Работа с памятью - 2007-09-28 13:14:21.510000
|
|
|
mindgen
Сообщений: 12
Оценки: 0
Присоединился: 2007-09-27 09:32:38.196666
|
Так делать тоже не выход,в моем случае. Буду делать глобальную мапу. Где ключ-адрес, азначение кол-во ссылок на адрес. Извращенство конечно, а что делать… )
|
|
|
|
|