Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2002.11.11;
Скачать: CL | DM;

Вниз

тип 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;
Скачать: CL | DM;

Наверх




Память: 0.54 MB
Время: 0.024 c
14-34217
Кот Бегемот
2002-10-22 16:57
2002.11.11
Да здравствует безболезненное отмечание Дня Рождения :)


1-34068
Alexey3
2002-10-31 04:20
2002.11.11
Запуск программ из Delphi


1-34098
vvolkov
2002-10-31 13:51
2002.11.11
Сохранение TControl


1-34028
race1
2002-11-02 17:33
2002.11.11
снова массивы


1-34091
Zergling
2002-10-30 06:15
2002.11.11
Как корректно завершить работу потоков в программе!?