Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Высвобождение памяти после выполнения функции 
:(
    Опции темы
Matrex
Дата 5.3.2009, 14:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 96
Регистрация: 31.1.2006

Репутация: нет
Всего: 2



Функция из сторонней библиотеки (написанной на С) возвращает указатель Р на массив типизированных записей (Type, Type, Type и т.д.) и N - количество этих записей. Собственно вопрос: как освободить занимаемую этими записями память? Функции типа dispose (Р) и FreeMem(Р) дают ошибку «Неверный указатель»

Это сообщение отредактировал(а) Matrex - 5.3.2009, 14:45
PM MAIL   Вверх
pseud
Дата 5.3.2009, 14:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Экспёрт Тыдыщ
***


Профиль
Группа: Завсегдатай
Сообщений: 1175
Регистрация: 18.5.2007
Где: Минск, Беларусь

Репутация: 10
Всего: 40



Код

Р := nil;


Добавлено через 1 минуту и 25 секунд
не претендует на истину


--------------------
Испытание чужого терпения можно считать успешным, если оно лопнуло...
PM MAIL   Вверх
Matrex
Дата 5.3.2009, 15:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 96
Регистрация: 31.1.2006

Репутация: нет
Всего: 2



Если бы… Не все так просто… Все равно наблюдается рост памяти. Я думаю, что связано это с представлением данных, которые эта функция возвращает: т.е. функция возвращает не массив указателей, а просто последовательность данных определенной структуры, поэтому указывая dispose (Р) или FreeMem(Р) или P:=nil я в лучшем случае обнулю только первую запись… Вот пример кода:

Код

Type rData=record
  Summ:integer;
End;
pData=^rData

procedure myObjectGet;
var count:integer;// количество записей (выше обозначено N)
      data:pData; // указатель на данные (выше обозначено P)
      r,ss:integer;    
begin
if getObject(count, data)<>cOk then begin showmessage(‘Error’);exit;end;

r:=0; while r<>count do begin
// доступ к данным    
ss:=data.Summ*2;
// нарастить адрес для выборки следующей записи
data:= pData (Integer(data)+SizeOf(data^));
inc (r);
end;

data:=nil; // обнулить что ? указатель на первую запись?
end;


Это сообщение отредактировал(а) Matrex - 5.3.2009, 15:13
PM MAIL   Вверх
Alexeis
Дата 5.3.2009, 15:21 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 109
Всего: 459



Matrex, это ошибка проектирования, если необходимая функция не экспортируется то освободить память нельзя. 
Р := nil; освобождает интерфейс или автоматический объект делфи. 


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
CodeMonkey
Дата 5.3.2009, 15:25 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 38
Всего: 89



В описании функции должно быть указано, как следует освобождать после неё память. Для этого часто из библиотеки экспортируется спец. функция очистки. Иногда в качестве таковой выступает системная, например, LocalFree.
Пытаться освободить память дельфическим менеджером памяти - принципиально неверно.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
Matrex
Дата 5.3.2009, 15:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 96
Регистрация: 31.1.2006

Репутация: нет
Всего: 2



Ясно. Спасибо за ответы.

Это сообщение отредактировал(а) Matrex - 5.3.2009, 15:40
PM MAIL   Вверх
MetalFan
Дата 5.3.2009, 16:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 62
Всего: 128



скорее всего освобождением памяти занимается сама библиотека...
кстати, приведен жуткий код) который можно местами упростить


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
Christoph
Дата 5.3.2009, 23:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 667
Регистрация: 23.1.2008
Где: Харьков

Репутация: 1
Всего: 11



Цитата(CodeMonkey @  5.3.2009,  15:25 Найти цитируемый пост)
Пытаться освободить память дельфическим менеджером памяти - принципиально неверно.

Как то не могу понять эту фразу, а можно выбрать какой я хочу использовать менеджер памяти? ведь менеджер память работает без ведома пользователя, надо тебе менджер памяти выделил память, надо удалил. Может быть я неправ


--------------------
user posted image
PM MAIL ICQ   Вверх
Alexeis
Дата 5.3.2009, 23:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 109
Всего: 459



Цитата(Christoph @  5.3.2009,  22:47 Найти цитируемый пост)
Как то не могу понять эту фразу, а можно выбрать какой я хочу использовать менеджер памяти? ведь менеджер память работает без ведома пользователя, надо тебе менджер памяти выделил память, надо удалил. Может быть я неправ 

  Менеджеры памяти разные бывают, почему они должны быть совместимы?


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Riply
Дата 5.3.2009, 23:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Комодератор
Сообщений: 572
Регистрация: 27.3.2007
Где: St. Petersburg

Репутация: 3
Всего: 32



Цитата(Christoph @  5.3.2009,  23:47 Найти цитируемый пост)
Как то не могу понять эту фразу


Чем выделял - тем и надо освобождать.
Т.е. в данном случае тем, чем "выделяла" ф-ия.
PM MAIL   Вверх
Christoph
Дата 6.3.2009, 00:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 667
Регистрация: 23.1.2008
Где: Харьков

Репутация: 1
Всего: 11



Ну в Делфи стоит же единственный менеджер памяти,можно ли взять какой то чужой менеджер  вместо стандартного делфийского?


--------------------
user posted image
PM MAIL ICQ   Вверх
CodeMonkey
Дата 6.3.2009, 11:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 38
Всего: 89



Цитата(Christoph @  5.3.2009,  23:47 Найти цитируемый пост)
Как то не могу понять эту фразу

И FreeMem, и Dispose и об-nil-ние интерфейсов и массивов, и очистка строк - все они вызывают одну и ту же стандартную системную функцию _FreeMem. Которая, по-умолчанию, вызывает функцию освобождения памяти стандартного менеджера Delphi MemoryManager.FreeMem.

Цитата(Christoph @  6.3.2009,  00:23 Найти цитируемый пост)
можно ли взять какой то чужой менеджер  вместо стандартного делфийского?

Можно. Для этого достаточно вызвать SetMemoryManager, предварительно вписав в структуру TMemoryManager указатели на управляющие функции. 
Вопрос в другом: а где ты его возьмёшь, этот чужой менеджер памяти? Библиотека писана на C. Там используется какой-то внутренний менеджер памяти, доступа к которому у тебя нет никакого. Точно так же, как библиотека, писанная на Delphi, не выставляет наружу никаких функций (а особенно управление менеджером памяти), пока ты явно это не укажешь в exports. Ну и как ты до достучишся до чужого менеджера памяти? Никак. Поэтому библиотека и должна предоставлять функцию освобождения памяти.

Но даже, если бы вдруг у тебя на руках чудесным образом оказались бы указатели на чей-то чужой менеджер памяти, заменять им свой - крайне плохая идея. И вот почему. До того момента, как вы получили в свои руки чужой менеджер памяти и установили его, у вас уже выделена целая куча памяти. Любой блок может быть освобождён сразу после того, как вы установите новый менеджер. Но запрос-то на освобождение придёт не вашему менеджеру, а чужому! Который про этот блок памяти ничего не знает! Например:

Код
var
  MM: TMemoryManager;
  S: String; // <- как-то используется для получения чужого MM
begin
  ... // <- как-то получаем чужой MM
  SetMemoryManager(MM);
end; // <- здесь наступает ГГ, потому что тут освобождается S. Она была выделена нашим менеджером памяти, а освобождается чужим


И наоборот. Поработали, выгружаем библиотеку. А при выгрузке менеджер памяти библиотеки финализируется и освобождает всю выделенную им память:

Код
var
  S: String; 
begin
  ... // <- как-то используется S
  SetMemoryManager(OldMM); 
  FreeLibrary(DllHandle); // <- выгружаем DLL, её менеджер памяти освобождает свою память
  ShowMessage(S); // <- AV, т.к. память под S была освобождена
  // или
  S := ''; // <- ещё одно ГГ, т.к. запрос на освобождение опять получил не тот MM
end;


Именно поэтому нужно чётко разграничивать: какие блоки памяти ты выделил сам, а какие - выделил тебе чужой дядька. И свою память ты освобождаешь сам, а чужую - отдаёшь обратно дядьке на освобождение.

Добавлено @ 11:29
Да, если бы:
1). Библиотека была бы статически связана с твоим exe, а не грузилась бы динамически.
и
2). Менеджер памяти или в exe или в библиотеке заменялся бы на чужой автоматически загрузчиком ОС.

То использование чужого ММ было бы вполне безопасно.

Но это подразумевает, что:
1). Библиотеки нельзя будет загружать динамически!
2). Существует какой-то стандарт на MM ВСЕХ библиотек, писанных в ЛЮБЫХ языках (чего нет) (*).
3). Загрузчик ОС как-то определяет, кому отдать предпочтение: то-ли подпихнуть в exe менеджер памяти в библиотеке, то-ли подпихнуть в библиотеку менеджер памяти в exe. А если к тому же эти MM отличаются по эффективности в разы, то при неудачном выборе не миновать табуретки в мониторе.

Разделяемый менеджер памяти (типа ShareMem, SimpleShareMem или в виде пакета) решает эту задачу таким образом, что менеджер памяти устанавливается ПЕРВЫМ же действием в программе. При этом используется само-придуманный стандарт. Который могут использовать только те, кто про него в курсе. А это как правило, только Delphi или C++ Builder приложения.

Примечание:
(*) Не уверен, как с этим обстоит дело в .NET.

Это сообщение отредактировал(а) CodeMonkey - 6.3.2009, 12:06


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
Christoph
Дата 6.3.2009, 15:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 667
Регистрация: 23.1.2008
Где: Харьков

Репутация: 1
Всего: 11



спасибо немного разобрался,CodeMonkey, +1


--------------------
user posted image
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0861 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.