Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2004.07.18;
Скачать: [xml.tar.bz2];

Вниз

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;
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.
Если я правильно понял, то при удалении объект пытается очистить память по указателю FField и не может. А может я ошибаюсь?


 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.55 MB
Время: 0.042 c
14-1088144458
YurikGL
2004-06-25 10:20
2004.07.18
Во сколько оценить компьютер


1-1088849976
serg128
2004-07-03 14:19
2004.07.18
Как получить идентификатор (дескриптор) активного приложения?


6-1084799281
delpher_gray
2004-05-17 17:08
2004.07.18
Зависание программы при TIdHTTP.Get()


6-1084900734
pnr
2004-05-18 21:18
2004.07.18
Неправильная обработка множественных пробелов в IdFTP


1-1089179521
Beton
2004-07-07 09:52
2004.07.18
Повторный запуск приложения





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский