![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
FreeAndNil никого не убивает, иногда, но постоянно
АлексейК © (2004-07-05 13:30:00)Кусочек кода
function GetValue(...):....;
var MyForm:TMyForm;
begin
MyForm:=TMyForm.Create(...);
with MyForm do
....
ShowModal;
Result:=x;
end;
FreeAndNil(MyForm);
end.
На строке FreeAndNil(MyForm) возникает ошибка Invalid pointer operator. MyForm реально ссылается на объект (сравнивал значение при создании формы и перед уничтожением - идентичны) и объект не уничтожается. При этом ошибка возникает не при каждом вызове, но стабильно, бывает на пятом-шестом, иногда и при первом (но редко), иногда на втором, бывает и десяток вызовов нормально проходят. Форма безвариантна, при каждои вызове одни и те же действия. Ну в чем искать причину, хоть примерно.
Digitman (2004-07-06 12:13:00) [1]
> почему же тогда все работает и без ShareMem'a
потому что, наверно, оба проекта собраны с опцией BwRTP, в этом случае менеджер памяти так же единый
использование ShareMem перекрывает (делает необязательным) необходимость сборки обоих проектов с опцией BwRTP, потому что при этом оба приложения собираются таким образом, что с момента старта и до конца работы они будут использовать единый внешний менеджер, реализованный Борландом в borlandmm.dll
если же ShareMem не указан вобоих проектах, то единый экз-р менеджера памяти будет использован только в случае сборки обоих проектов с опцией BwRTP, в противном случае экз-ры менеджеров памяти будут различными
все вышесказанное относится к случаю, когда оба проекта разработаны в Делфи, причем при соглашении о сборке с ран-тайм пакетами вступает в силу еще одно ограничение - версии Делфи при разработке обоих проектов д.б. одинаковы
когда же речь идет о вызывающем проекте, разработанном не в Делфи и не в С-Билдере, ни одно из упомянутых простых соглашений не подходит, ибо вызывающее приложение м.б. разработано в иных средах (например, MSVC), компиляторы которых не имеют ни малейшего представления об используемом в Делфи-ДЛЛ менеджере памяти
KADAN (2004-07-06 11:54:00) [2]jack128
Да, я это знаю. Но почему же тогда все работает и без ShareMem'a?
jack128 (2004-07-06 11:16:00) [3]
> память выделенная в библиотеке может свободно использоваться
> в приложении
нет. Есть такое понятие - "Менеджер памяти" - именно он выделяет/освобождает память. Если менеджеры памяти в dll и EXE разные, так как ты говоришь память использовать нельзя. В Дельфи единый менеджер памяти для DLL и EXE используетсяесли ты подключаешь модуль ShareMem к проэктам(к ОБОИМ - и обязятельно первым юнитов в списке uses файла проэкта!!!)..
KSergey (2004-07-06 11:12:00) [4]> [29] KADAN © (06.07.04 11:06)
> Я всегда считал, что если ДЛЛ проецируется на адресное пространство
> данного процесса то и память (и указатели) у них общие и,
> следовательно, память выделенная в библиотеке может свободно
> использоваться в приложении. Объясните где я ошибаюсь.
Использоваться может
Но надо четко понимать и следить, чтобы память в момент ее использования была действительно выделена.
KADAN (2004-07-06 11:06:00) [5]2 Digitman
Я всегда считал, что если ДЛЛ проецируется на адресное пространство данного процесса то и память (и указатели) у них общие и, следовательно, память выделенная в библиотеке может свободно использоваться в приложении. Объясните где я ошибаюсь.
Digitman (2004-07-06 10:34:00) [6]
> АлексейК
еще раз заостряю твое внимание на соглашениях :
если не соблюдаются соглашения о ран-тайм пакетах и/или об использовании ЕДИНОГО менеджера памяти в ЕХЕ и ДЛЛ, то при попытке освобождения в вызывающем приложении возвращенной ему из ДЛЛ памяти ты получишь точно такую же ошибку, если менеджеры памяти в вызывающем приложении и твоей ДЛЛ разные .. причем - ВНЕ зависимости от корректности выделения и заполнения блока памяти в ДЛЛ
Digitman (2004-07-06 10:26:00) [7]
> АлексейК (06.07.04 10:00) [24]
> Да причем тут соглашения, речь идет о конкретной ошибке.
ты вообще слушать умеешь или нет ?
я тебе сказал - отказ Invalid Pointer Operation происходит не в ДЛЛ и не на строчке FreeAndNil !
используй отладчик в режиме пошаговой трассировки и выясняй сначала, на КАКОЙ КОНКРЕТНО строчке происходит исключение, потом и разговор будет конкретный !
а то как в том анекдоте - ищешь не там где лежит, а там где светло ..
АлексейК (2004-07-06 10:26:00) [8]>KADAN © (06.07.04 10:15) [25]
Спасибо, действительно, ошибся при определии длины строки. Как всегда, чем банальнее ошибка, тем тяжелее она находится.
KADAN (2004-07-06 10:15:00) [9]постарался воспроизвести:
function GetValue(aHandle:THandle):pChar;
var
Form2: TForm2;
begin
Application.Handle:=aHandle;
Form2:=TForm2.Create(Application);
with form2 do begin
showmodal;
result:=FField;
end;
FreeAndNil(Form2);
end;
procedure TForm2.Button1Click(Sender: TObject);
begin
FField := StrAlloc (длина);
StrCopy (FField, pchar(Edit1.text));
close;
end;
в приложении делаюLabel1.caption:=GetValue(application.handle);
'Invalid pointer operation' возникает только при неправильном выделении памяти под FField. (например, когда выделяю 4 байта, а передаю 'Edit1')
АлексейК (2004-07-06 10:00:00) [10]о соглашениях использования конкретного менеджера памяти ты не обмолвился, видимо их попросту нет.. грош цена таким соглашениям
изволь описать соглашения от и до, тогда о чем-то говорить можно будет
Да причем тут соглашения, речь идет о конкретной ошибке.
Digitman (2004-07-06 09:36:00) [11]
> АлексейК (06.07.04 09:28) [22]
> эту DLL' ку я не для себя писал, вернее не только для себя,
> и по этому должен придерживаться определенных соглашений
о соглашениях использования конкретного менеджера памяти ты не обмолвился, видимо их попросту нет.. грош цена таким соглашениям
изволь описать соглашения от и до, тогда о чем-то говорить можно будет
АлексейК (2004-07-06 09:28:00) [12]Digitman © (06.07.04 08:57) [18]
> Абсолютно согласен
что ж тогда в заблуждение людей вводишь ?
Ну ты же в заблуждение не ввелся. ShareMem пробовал, результат тот же, да и не должно в данном случае это быть приципиально. Однако если скажем избавляюсь от StrAlloc, то есть ремарю
{FField: = StrAlloc (100);
StrCopy (FField, 'Пример');}
и реально не присваеваю значение возращаемого параметра для функции, то ошибка пропадает, значит проблема все таки с памятью. А в модуле действительно описан только класс TMyForm и функция GetValue, там больше нечего нет.
- либо полностью пересматривай логику - память должна выделяться вызывающим кодом, вызываемый же код либо должен заполнить ее либо вернуть отказ , если переданной для заполнения памяти недостаточно
Я даже приблизительно не могу сказать, сколько этой памяти мне будет нужно. И тем более эту DLL' ку я не для себя писал, вернее не только для себя, и по этому должен придерживаться определенных соглашений. То есть я не могу пойти и сказать, что бы все работало делай так или эдак.
Digitman (2004-07-06 09:20:00) [13]
> KADAN © (06.07.04 09:06) [19]
автор выделяет память под результат в ДЛЛ , а освобождает ее в ЕХЕ
если оба проекта не используют ни пакеты времени выполнения ни Sharemem, то менеджеры памяти у них разные, и при освобождении памяти как раз и происходит исключение
Silver Alex (2004-07-06 09:19:00) [14]на сколько я понял переменная var MyForm:TMyForm; локальная , обьявлена в функции function GetValue(...), и кроме как в этой функиции больше нигде не видна. Так зачем тогда FreeAndNil(MyForm) ?Все равно ведь никто не сможет обратиться к этой переменной , что бы провверить Nil она или нет.По моему тут достаточно просто MyForm.Free;
KADAN (2004-07-06 09:06:00) [15]И все-таки меня терзают смутные сомнения, что FField и MyForm - не единственные указатели в этом модуле.
Digitman (2004-07-06 08:57:00) [16]
> Абсолютно согласен
что ж тогда в заблуждение людей вводишь ?
- либо собери оба проекта с опцией Build With Run-Time Packages
- либо в dpr-файлах обоих проектов в USES первой позицией укажи ShareMem
- либо полностью пересматривай логику - память должна выделяться вызывающим кодом, вызываемый же код либо должен заполнить ее либо вернуть отказ , если переданной для заполнения памяти недостаточно
последнее "либо" - наиболее лучшее решение, потому что вызывающий в общем случае код необязательно является делфи-кодом, а значит ни первое ни второе "либо" не подойдут
KSergey (2004-07-06 08:51:00) [17]Я так подозреваю, что возможно проблема еще и в dll
как, что, где в ней - мы про то не ведаем...
Вам еще не надоело гадать?
АлексейК (2004-07-06 08:50:00) [18]Digitman © (06.07.04 08:35) [14]
> АлексейК
> На строке FreeAndNil(MyForm) возникает ошибка Invalid pointer
> operator
не верю.
не на этой строке возбуждается исключение
Абсолютно согласен, однако ошибка остается. И главное не понятно, почему она не возникает при каждом вызове или по какой-либо закономерности, ведь действия формы безвариантны, вызвали, взяли параметер, закрыли, даже длина возвращаемой строки не отличается более чем на 15-20 символов.
KADAN (2004-07-06 08:44:00) [19]точно, не на этой. приведи код поподробнее.
Digitman (2004-07-06 08:35:00) [20]
> АлексейК
> На строке FreeAndNil(MyForm) возникает ошибка Invalid pointer
> operator
не верю.
не на этой строке возбуждается исключение