Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

FreeAndNil никого не убивает, иногда, но постоянно


Страницы:   1 2

АлексейК ©   (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


не верю.
не на этой строке возбуждается исключение


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо