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

Вниз

тип string, освобождение памяти   Найти похожие ветки 

 
robot 415   (2002-10-23 19:11) [0]

Нужно ли освобождать память в таком коде:
var
P: Pointer;
begin
string(P) := "abc";
end;


 
LongIsland   (2002-10-23 19:29) [1]

Нет


 
robot 415   (2002-10-23 19:33) [2]

А почему? Ведь подсчет ссылок автоматически ведется только для переменных типа string?


 
LongIsland   (2002-10-23 19:36) [3]

var
P: Pointer;
begin
integer(P) := "abc";
end;

Тогда уж и здесь освобождайте

arr: array of String;

И здесь тоже...


 
robot 415   (2002-10-23 19:42) [4]

integer(P) := "abc"; // не работает
array of string - это понятно, потому что of string.


 
Anatoly Podgoretsky   (2002-10-23 19:54) [5]

Так вообще нельзя писать


 
Andrey   (2002-10-23 19:58) [6]

А ты поробуй немного разширить программу:

var
P: Pointer;
s: string;
begin
string(P) := "abcefg";
s:="abcefg";
end;


Поставить останов на строке string(P) := "abcefg";
Запустить программу под отладчиком, и когда отладчик дойдет до этой точки останова нажать Ctrl+Alt+C. Откроется замечательное окошко которое будет называтся CPU. В этом окошке можно посмотреть что из твоих исходников делает компилятор. Как видишь строки соответствующие string(P) := "abcefg"; и s:="abcefg"; различаются несущественно, а значит и обробатываются одинаково. Следовательно если компилятор освободит память для строки s:="abcefg"; то он и для строки string(P) := "abcefg"; тоже освободит память.

Уф... Какой я разговорчивый :)


 
robot 415   (2002-10-23 20:04) [7]

2Anatoly Podgoretsky
Как нельзя писать?
2Andrey
Спасибо, но если память для них выделяется одинаково, это не значит, что она и освобождается одинаково.


 
LongIsland   (2002-10-23 20:14) [8]


> robot 415 (23.10.02 20:04)

Прошу прощения за первый пример, сгоряча написал:-)

Хорошо, пойдем от противного, КАК Вы собираетесь освободить помять?


 
robot 415   (2002-10-23 20:19) [9]

Память я собираюсь освобождать так:
string(P) := "";


 
LongIsland   (2002-10-23 20:22) [10]


> robot 415 (23.10.02 20:19)

Простите, но Вы ее не освободили...


 
robot 415   (2002-10-23 20:27) [11]

>Простите, но Вы ее не освободили...
Жаль... я старался :)
А как же ее освободить? Никак? Значит, поэтому и не надо?


 
LongIsland   (2002-10-23 20:33) [12]


> robot 415 (23.10.02 20:27)

Для нетипизированного указателя это делается через FreeMem. Теперь попробуйте вставить в Ваш код эту функцию:-)


 
Andrey   (2002-10-23 20:41) [13]

>robot 415 (23.10.02 20:04)
В принципе оно конечно да. Совсем не обязательно если память выделяется одинаково, то она и освобождается одинаково...

Но я пологаю, что специалисты Борланда ради соблюдения некоторых стандартов, в области работы с менеджером памяти, для освобождения ресурсов будут придерживатся единообразия.
А именно "Память э..алокированая определенной функцией должна быть освобождена другой определенной функцией"
Тобишь:

AllocMem() FreeMem()
GlobalAlloc() GlobalFree()
GetMem() FreeMem()
New() Dispose()
StrAlloc() StrDispose()
StrNew() StrDispose()
VirtualAlloc() VirtualFree()


Функция AllocMem() является оберткой для GetMem()
StrNew() для StrAlloc(). Тоесть как видите соблюдается вобщем-то довольно строгая последовательность
ФункцияЗанять-ФункцияОсвободить. Из этого (и еще из своего скромного опыта :)) я сделал вывод, поспешный вывод, что память будет освобождена (правда я досихпор думаю, что память всетаки освободится). Доказать обратное, что память не освобождается я тоже немогу, покрайне мере сейчас немогу.

Короче я не полностью уверен что память освободится. Но и доказательств что она не освободится тоже не нашел.

P.S. Списки функций из книги "Delphi 4. Руководство разработчика".


 
robot 415   (2002-10-23 20:43) [14]

Я же GetMem не делал.
GetMem выполняется при присваивании строковой переменной нового значения. Я думал, что уменьшение счетчика ссылок и FreeMem (в этом примере) выполняется при выходе строковой переменной из оьласти видимости, а это выполняется для любой переменной, которую можно привести к string. А почему? Где хранится информация о том, что P: Pointer на самом деле является строкой?


 
robot 415   (2002-10-23 20:48) [15]

2Andrey
Усе, понятно! (Идем к разбираться к менеджеру памяти)
Память на самом деле освобождается, проверено.


 
LongIsland   (2002-10-23 20:48) [16]


> robot 415 (23.10.02 20:43)


> А почему? Где хранится информация о том, что P: Pointer
> на самом деле является строкой?

Да, в общем-то и нигде, насколько я понимаю:-) Это Ваше дело следить за этим. А компьютеру все равно, что там находится:-)


 
Romkin   (2002-10-23 20:49) [17]

точно смотреть еще не смотрел, но, ИМХО:
1. string(P) := "aaa"; - среда память не освободит, коли преобразовали тип, так и освобождайте сами
2. string(P) :=""; - является именно тем, что нужно - память должна освободиться. Чтобы убедится в этом, просто проверьте Р на nil после этой строки, если да - значит, все в порядке.
Другой вопрос, зачем это надо?


 
robot 415   (2002-10-23 20:51) [18]

2LongIsland © (23.10.02 20:48)
Но если мое дело, то как освободить память? Никак. И т.д.
На самом деле менеджер памяти за этим следит, как я понял.


 
robot 415   (2002-10-23 20:55) [19]

2Romkin
Память освобождается, проверял с помощью CheckMem. В этом-то и понт. Или ошибка в CheckMem. Оба разультата для меня очень неожиданны.



 
robot 415   (2002-10-23 20:57) [20]

2Romkin
>Другой вопрос, зачем это надо?
Очень просто, чтобы хранить еще одну строку в TStrings.Objects - начал проверять, что будет, пришел к такому вопросу.


 
McSimm   (2002-10-24 10:02) [21]

Так вообще нельзя писать. Некорректно.

1. String(P) - некорректное в данном случае приведение. Так как P не является указателем на блок данных, который компилятор делает для String; В общем случае код должен приводить к AV. Т.к. для P aka String в счетчиках по адресам P-4 и P-8 могут находиться произвольные данные.

2. Забыв про некорректность кода, хочу заметить что не при всех операциях со строками происходит выделение / освобождение памяти. Например при работе со строковыми литералами.


 
McSimm   (2002-10-24 10:21) [22]

>чтобы хранить еще одну строку в TStrings.Objects
Почувствуйте разницу:
1. String(P) := ... означает:
"Считай блок памяти по адресу P строкой и сделай для этой якобы строки присвоение"

2. P := PChar(...);
"Возьми адрес некторой строки и запомни его в P"

Первый вариант некорректен по причине неверного преобразования типа
Второй вариант корректен, но для хранения строк не годится, т.к. время жизни строки не продливается и будет равнятся времени жизни той строки что в скобках. Это означает, что программа освободит память раньше, чем вам этого, возможно, хочется. Т.е. в TStringList будут храниться указатели на освобожденную память.


 
McSimm   (2002-10-24 10:39) [23]

Да. Чтобы все было красиво и по правилам, рекомендую такую простую схему:

var
P: PString;
....
New(P);
StringList.Objects[i] := TObject(P);

...
При удалениях в StringList или перед Free необходимо сделать
Dispose(PString(StringList.Objects[i]))



 
robot 415   (2002-10-24 11:19) [24]

2McSimm
Спасибо за ответ, еще пара вопросов, если можно

> 1. String(P) - некорректное в данном случае приведение.
> Так как P не является указателем на блок данных, который
> компилятор делает для String; В общем случае код должен
> приводить к AV. Т.к. для P aka String в счетчиках по адресам
> P-4 и P-8 могут находиться произвольные данные.

А если сначала сделать P := nil? (данные по адресам P-4 и P-8 будут игнорироваться) Так будет правильно? (Освобождать так: string(P) := "")

2McSimm © (24.10.02 10:39)
Я так и делал, потом подумал - ведь New(P) выделяет память под еще один указатель (4 байта), зачем - у нас ведь и так она есть (Objects[i])






 
McSimm   (2002-10-24 11:44) [25]

>А если сначала сделать P := nil? Так будет правильно?(Освобождать так: string(P) := "")

Теоретически - да.
Практически, советую писать код более понятным и предсказуемым.

>ведь New(P) выделяет память под еще один указатель (4 байта), зачем - у нас ведь и так она есть (Objects[i])

New procedure
Creates a new dynamic variable and sets P to point to it.
В нашем случае создается динамическая переменная типа String и указатель на нее помещается в P. Этот указатель на String мы и храним в Objects[i].
Но размещать сами String в массиве Objects - явно неверно.


 
robot 415   (2002-10-24 11:54) [26]

Спасибо.
Еще вопрос, если я Вас не утомил.
Ведь в переменной типа string хранится указатель на структуру, содржащую счетчик ссылок и длину, и далее сама строка. Память под эту структуру и под строку выделяется при присваивании строковой переменной нового значения, а New(P), P: PString создает только лишь сам указатель и ининциализирует его нулем. Поэтому все-таки непонятно, почему размещать сами String в массиве Objects неверно (если сделать Objects[I] := nil).


 
McSimm   (2002-10-24 12:13) [27]

Все нижесказанное - мое скромное мнение:

1. Плохой стиль программирования. Гарантия проблем.
Ради чего? Ради экономии 4х байт? не стоит

2. А каким образом?
Вариант
String(SL.Objects[i]) := ...
невозможен. Это свойство, а не поле.
Вариант
P := nil;
String(P) := ...
SL.Objects[i] := TObject(P)
я извиняюсь, но это больше извращение, чем программирование. Уважительнее надо относится к программе и программа ответит тем же.

Разумеется, пиши как хочется. При достаточно ясном представлении о механизмах работы, можно писать как угодно и без ошибок.


 
robot 415   (2002-10-24 12:17) [28]

Спасибо, всего хорошего!



Страницы: 1 вся ветка

Форум: "Потрепаться";
Текущий архив: 2002.11.11;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.52 MB
Время: 0.007 c
1-33933
FKL
2002-11-01 00:22
2002.11.11
Файлы


1-34002
Anar
2002-10-30 16:31
2002.11.11
Скрыть заголовок формы


6-34144
Ruslan S
2002-09-12 07:44
2002.11.11
Определение страны по IP адресу


3-33914
Tornado
2002-10-23 08:59
2002.11.11
ADOTable.Filter ?


1-33934
KDCF
2002-10-31 22:41
2002.11.11
Народ помогите!!!





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский