Текущий архив: 2004.07.18;
Скачать: CL | DM;
Вниз
FreeAndNil никого не убивает, иногда, но постоянно Найти похожие ветки
← →
АлексейК (2004-07-05 13:30) [0]Кусочек кода
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 реально ссылается на объект (сравнивал значение при создании формы и перед уничтожением - идентичны) и объект не уничтожается. При этом ошибка возникает не при каждом вызове, но стабильно, бывает на пятом-шестом, иногда и при первом (но редко), иногда на втором, бывает и десяток вызовов нормально проходят. Форма безвариантна, при каждои вызове одни и те же действия. Ну в чем искать причину, хоть примерно.
← →
VMcL © (2004-07-05 13:34) [1]>>АлексейК (05.07.04 13:30)
Что на строкеFreeAndNil(MyForm);
говорит клавиша F7 в режиме отладки в IDE?
← →
TUser © (2004-07-05 13:39) [2]А в OnClose у этой формы не написано caFree случайно?
← →
АлексейК (2004-07-05 13:46) [3]Формочка вызывается из DLL.
OnClouse не прописан вообще.
← →
Dok_3D © (2004-07-05 13:47) [4]Ошибка у вас программе, милейший, не сомневайтесь.
Уже по строчке "with MyForm do" видно, что вы любитель этой ошибкообильной конструкции.
Отлдаживаться нужно, отлаживаться.
← →
icWasya © (2004-07-05 13:49) [5]Судя по тексту
end;
FreeAndNil(MyForm);
end.
процедура FreeAndNil выызывается в секции инициализации модуля. Или я не понял? Приведите кода побольше.
← →
GuAV © (2004-07-05 13:52) [6]а если
MyForm.Release
MyForm:=nil
заместо freeandnil ?
> Уже по строчке "with MyForm do" видно, что вы любитель этой
> ошибкообильной конструкции.
Конструкция не ошибкообильна, если уметь аккуратно применить. я бы тут тоже юзал with MyForm do try (а кстати release - в finally)
← →
АлексейК (2004-07-05 13:52) [7]Я на Delphi и не грешу, только ошибка не постоянная, потому и выловить не могу.
Судя по тексту
end;
FreeAndNil(MyForm);
end.
процедура FreeAndNil выызывается в секции инициализации модуля. Или я не понял? Приведите кода побольше....
FreeAndNil(MyForm);
end. //function GetValue
← →
GuAV © (2004-07-05 13:54) [8]end. //function GetValue
а точка тогда что здесь делает?
← →
АлексейК (2004-07-05 13:56) [9]GuAV © (05.07.04 13:54) [8]
end. //function GetValue
а точка тогда что здесь делает?
Да запятая там конечно, просто голова уже тяжелая.
← →
TUser © (2004-07-05 14:48) [10]Наверное, надо рассказать про то, что такое MyForm. Там чего-нибудь создается/память выделяется и т.д.? Что при ее создании/уничтожении происходит?
← →
АлексейК (2004-07-06 07:13) [11]Тему для размышлений нашел, привожу альтернативный, упрощенный код
(модуль зашит в DLL и вызывается с основной программы)unit uMyForm;
Если я правильно понял, то при удалении объект пытается очистить память по указателю FField и не может. А может я ошибаюсь?
interface
type
TMyForm=class(TForm)//вообщем просто модальная форма с гридом
...
private
...
FField:PChar;
public
...
end;
function GetValue(aHandle:THandle):pChar;//декларируется для экспорта из DLL в модуле проекта
implementation
function GetValue;
var MyForm:TMyForm;
begin
Application.Handle:=aHandle;
MyForm:=TMyForm.Create(Application);
with MyForm do
begin
...
ShowModal;
Result:=FField;
end;
FreeAndNil(MyForm);
end;//GetValue
//процедура берет значение и закрывает форму.
procedure TMyForm.btn_okClick(Sender: TObject);
begin
FField: = StrAlloc (100);
StrCopy (FField, "Пример");
close;
end;
end.
← →
KADAN © (2004-07-06 07:38) [12]по-моему форма при уничтожении должна очищать FField, если нет - то следовало бы... но и присваивать результату указатель, который потом очищается тоже не надо.
Делаешь StrAlloc с постоянным параметром 100, не проще ли завести array[0..100] of char, только отдельно от формы, и возвращать его?
← →
АлексейК (2004-07-06 08:17) [13]В программе StrAlloc не имеет постоянного значения параметра, то есть
StrAlloc(n),где n вычисляемая величина. При этом, обнуления указателя:
Result:=FField;
FField:=nil;
FreeAndNil(MyForm)
положения не меняет, ошибка все равно остается, и она появляется не всегда, хотя данные передаеются нормально, но из десяти вызовов формы вероятность ее появления около 95%.
← →
Digitman © (2004-07-06 08:35) [14]
> АлексейК
> На строке FreeAndNil(MyForm) возникает ошибка Invalid pointer
> operator
не верю.
не на этой строке возбуждается исключение
← →
KADAN © (2004-07-06 08:44) [15]точно, не на этой. приведи код поподробнее.
← →
АлексейК (2004-07-06 08:50) [16]Digitman © (06.07.04 08:35) [14]
> АлексейК
> На строке FreeAndNil(MyForm) возникает ошибка Invalid pointer
> operator
не верю.
не на этой строке возбуждается исключение
Абсолютно согласен, однако ошибка остается. И главное не понятно, почему она не возникает при каждом вызове или по какой-либо закономерности, ведь действия формы безвариантны, вызвали, взяли параметер, закрыли, даже длина возвращаемой строки не отличается более чем на 15-20 символов.
← →
KSergey © (2004-07-06 08:51) [17]Я так подозреваю, что возможно проблема еще и в dll
как, что, где в ней - мы про то не ведаем...
Вам еще не надоело гадать?
← →
Digitman © (2004-07-06 08:57) [18]
> Абсолютно согласен
что ж тогда в заблуждение людей вводишь ?
- либо собери оба проекта с опцией Build With Run-Time Packages
- либо в dpr-файлах обоих проектов в USES первой позицией укажи ShareMem
- либо полностью пересматривай логику - память должна выделяться вызывающим кодом, вызываемый же код либо должен заполнить ее либо вернуть отказ , если переданной для заполнения памяти недостаточно
последнее "либо" - наиболее лучшее решение, потому что вызывающий в общем случае код необязательно является делфи-кодом, а значит ни первое ни второе "либо" не подойдут
← →
KADAN © (2004-07-06 09:06) [19]И все-таки меня терзают смутные сомнения, что FField и MyForm - не единственные указатели в этом модуле.
← →
Silver Alex © (2004-07-06 09:19) [20]на сколько я понял переменная var MyForm:TMyForm; локальная , обьявлена в функции function GetValue(...), и кроме как в этой функиции больше нигде не видна. Так зачем тогда FreeAndNil(MyForm) ?Все равно ведь никто не сможет обратиться к этой переменной , что бы провверить Nil она или нет.По моему тут достаточно просто MyForm.Free;
← →
Digitman © (2004-07-06 09:20) [21]
> KADAN © (06.07.04 09:06) [19]
автор выделяет память под результат в ДЛЛ , а освобождает ее в ЕХЕ
если оба проекта не используют ни пакеты времени выполнения ни Sharemem, то менеджеры памяти у них разные, и при освобождении памяти как раз и происходит исключение
← →
АлексейК (2004-07-06 09:28) [22]Digitman © (06.07.04 08:57) [18]
> Абсолютно согласен
что ж тогда в заблуждение людей вводишь ?
Ну ты же в заблуждение не ввелся. ShareMem пробовал, результат тот же, да и не должно в данном случае это быть приципиально. Однако если скажем избавляюсь от StrAlloc, то есть ремарю{FField: = StrAlloc (100);
StrCopy (FField, "Пример");}
и реально не присваеваю значение возращаемого параметра для функции, то ошибка пропадает, значит проблема все таки с памятью. А в модуле действительно описан только класс TMyForm и функция GetValue, там больше нечего нет.
- либо полностью пересматривай логику - память должна выделяться вызывающим кодом, вызываемый же код либо должен заполнить ее либо вернуть отказ , если переданной для заполнения памяти недостаточно
Я даже приблизительно не могу сказать, сколько этой памяти мне будет нужно. И тем более эту DLL" ку я не для себя писал, вернее не только для себя, и по этому должен придерживаться определенных соглашений. То есть я не могу пойти и сказать, что бы все работало делай так или эдак.
← →
Digitman © (2004-07-06 09:36) [23]
> АлексейК (06.07.04 09:28) [22]
> эту DLL" ку я не для себя писал, вернее не только для себя,
> и по этому должен придерживаться определенных соглашений
о соглашениях использования конкретного менеджера памяти ты не обмолвился, видимо их попросту нет.. грош цена таким соглашениям
изволь описать соглашения от и до, тогда о чем-то говорить можно будет
← →
АлексейК (2004-07-06 10:00) [24]о соглашениях использования конкретного менеджера памяти ты не обмолвился, видимо их попросту нет.. грош цена таким соглашениям
изволь описать соглашения от и до, тогда о чем-то говорить можно будет
Да причем тут соглашения, речь идет о конкретной ошибке.
← →
KADAN © (2004-07-06 10:15) [25]постарался воспроизвести:
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")
← →
Digitman © (2004-07-06 10:26) [26]
> АлексейК (06.07.04 10:00) [24]
> Да причем тут соглашения, речь идет о конкретной ошибке.
ты вообще слушать умеешь или нет ?
я тебе сказал - отказ Invalid Pointer Operation происходит не в ДЛЛ и не на строчке FreeAndNil !
используй отладчик в режиме пошаговой трассировки и выясняй сначала, на КАКОЙ КОНКРЕТНО строчке происходит исключение, потом и разговор будет конкретный !
а то как в том анекдоте - ищешь не там где лежит, а там где светло ..
← →
АлексейК (2004-07-06 10:26) [27]>KADAN © (06.07.04 10:15) [25]
Спасибо, действительно, ошибся при определии длины строки. Как всегда, чем банальнее ошибка, тем тяжелее она находится.
← →
Digitman © (2004-07-06 10:34) [28]
> АлексейК
еще раз заостряю твое внимание на соглашениях :
если не соблюдаются соглашения о ран-тайм пакетах и/или об использовании ЕДИНОГО менеджера памяти в ЕХЕ и ДЛЛ, то при попытке освобождения в вызывающем приложении возвращенной ему из ДЛЛ памяти ты получишь точно такую же ошибку, если менеджеры памяти в вызывающем приложении и твоей ДЛЛ разные .. причем - ВНЕ зависимости от корректности выделения и заполнения блока памяти в ДЛЛ
← →
KADAN © (2004-07-06 11:06) [29]2 Digitman
Я всегда считал, что если ДЛЛ проецируется на адресное пространство данного процесса то и память (и указатели) у них общие и, следовательно, память выделенная в библиотеке может свободно использоваться в приложении. Объясните где я ошибаюсь.
← →
KSergey © (2004-07-06 11:12) [30]> [29] KADAN © (06.07.04 11:06)
> Я всегда считал, что если ДЛЛ проецируется на адресное пространство
> данного процесса то и память (и указатели) у них общие и,
> следовательно, память выделенная в библиотеке может свободно
> использоваться в приложении. Объясните где я ошибаюсь.
Использоваться может
Но надо четко понимать и следить, чтобы память в момент ее использования была действительно выделена.
← →
jack128 © (2004-07-06 11:16) [31]
> память выделенная в библиотеке может свободно использоваться
> в приложении
нет. Есть такое понятие - "Менеджер памяти" - именно он выделяет/освобождает память. Если менеджеры памяти в dll и EXE разные, так как ты говоришь память использовать нельзя. В Дельфи единый менеджер памяти для DLL и EXE используетсяесли ты подключаешь модуль ShareMem к проэктам(к ОБОИМ - и обязятельно первым юнитов в списке uses файла проэкта!!!)..
← →
KADAN © (2004-07-06 11:54) [32]jack128
Да, я это знаю. Но почему же тогда все работает и без ShareMem"a?
← →
Digitman © (2004-07-06 12:13) [33]
> почему же тогда все работает и без ShareMem"a
потому что, наверно, оба проекта собраны с опцией BwRTP, в этом случае менеджер памяти так же единый
использование ShareMem перекрывает (делает необязательным) необходимость сборки обоих проектов с опцией BwRTP, потому что при этом оба приложения собираются таким образом, что с момента старта и до конца работы они будут использовать единый внешний менеджер, реализованный Борландом в borlandmm.dll
если же ShareMem не указан вобоих проектах, то единый экз-р менеджера памяти будет использован только в случае сборки обоих проектов с опцией BwRTP, в противном случае экз-ры менеджеров памяти будут различными
все вышесказанное относится к случаю, когда оба проекта разработаны в Делфи, причем при соглашении о сборке с ран-тайм пакетами вступает в силу еще одно ограничение - версии Делфи при разработке обоих проектов д.б. одинаковы
когда же речь идет о вызывающем проекте, разработанном не в Делфи и не в С-Билдере, ни одно из упомянутых простых соглашений не подходит, ибо вызывающее приложение м.б. разработано в иных средах (например, MSVC), компиляторы которых не имеют ни малейшего представления об используемом в Делфи-ДЛЛ менеджере памяти
Страницы: 1 вся ветка
Текущий архив: 2004.07.18;
Скачать: CL | DM;
Память: 0.54 MB
Время: 0.033 c