Форум: "Потрепаться";
Текущий архив: 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.009 c