<?xml version='1.0' encoding="utf-8"?>
      <rss version='2.0'>
      <channel>
      <title>Форум на Исходниках.RU</title>
      <link>https://forum.sources.ru</link>
      <description>Форум на Исходниках.RU</description>
      <generator>Форум на Исходниках.RU</generator>
  	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=348550&amp;view=findpost&amp;p=2668231</guid>
        <pubDate>Fri, 13 Aug 2010 07:08:25 +0000</pubDate>
        <title>Некоторые хитрости динамического размещения и удаления записей с полями типа string</title>
        <link>https://forum.sources.ru/index.php?showtopic=348550&amp;view=findpost&amp;p=2668231</link>
        <description><![CDATA[Fr0sT: <strong class='tag-b'><span class="tag-color tag-color-named" data-value="purple" style="color: purple"><span class='tag-size' data-value='14' style='font-size:14pt;'>AllocMem + поля записи ссылочного типа</span></span></strong><br>
<br>
Очень часто приходится хранить список записей, место под которые выделяется динамически. При этом также не хочется ограничиваться лишь простыми типами данных, а использовать всю мощь ссылочных типов вроде string и DynArray. Однако при работе с ними есть некоторые тонкости.<br>
Во-первых, после выделения памяти под структуру все такие поля <strong class='tag-b'>необходимо</strong> занулять. Почему? Рассмотрим запись<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">type</div><div class="code_line">&nbsp;TRec = record</div><div class="code_line">&nbsp;&nbsp; s1: string;</div><div class="code_line">&nbsp;end;</div></ol></div></div></div></div><script>preloadCodeButtons('1');</script><br>
<br>
После выделения памяти через GetMem в полученной области находится случайный мусор. На месте s1 практически наверняка присутствует набор байт, который будет считаться указателем на строку. При первом же присвоении программа подумает, что в строке уже что-то есть, и попытается освободить память. Что, разумеется, приведёт к исключению. AllocMem сама обнуляет выделенную память, так что предпочтительней использовать именно её.<br>
<br>
Во-вторых, что уже сложнее, проблемы возникают при освобождении памяти. Поля ссылочного типа освобождаются неявно, с подсчётом ссылок. Если забивать их нулями, получим утечку памяти. Но и не вручную же каждый раз их все обнулять перед FreeMem&#33; К счастью, мне удалось найти решение - выход в способности Delphi копировать записи простым присваиванием. Задача решается созданием специальной нулевой записи соответствующего типа.<br>
<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">type TRec = record</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; s1, s2: string;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; arr: array of byte;</div><div class="code_line">&nbsp;&nbsp; &nbsp; end;</div><div class="code_line">&nbsp;</div><div class="code_line">var ZeroRec: TRec;</div><div class="code_line">&nbsp;</div><div class="code_line">...</div><div class="code_line">&nbsp;</div><div class="code_line">initialization</div><div class="code_line">&nbsp;&nbsp;ZeroMem(ZeroRec, SizeOf(ZeroRec));</div><div class="code_line">&nbsp;</div><div class="code_line">...</div></ol></div></div></div></div><br>
<br>
Способ использования:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">var pRec: ^TRec;</div><div class="code_line">&nbsp;</div><div class="code_line">...</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;pRec := AllocMem(SizeOf(TRec));</div><div class="code_line">&nbsp;&nbsp;pRec.s1 := &#39;wefwefwef&#39;;</div><div class="code_line">&nbsp;&nbsp;pRec.s2 := &#39;234234234&#39;;</div><div class="code_line">&nbsp;&nbsp;SetLength(pRec.arr, 10);</div><div class="code_line">&nbsp;&nbsp;pRec^ := ZeroRec;</div><div class="code_line">&nbsp;&nbsp;FreeMem(pRec);</div></ol></div></div></div></div><br>
<br>
Как можно убедиться, трассируя ассемблерный код на строчке pRec^ := ZeroRec, программа очищает все ссылочные поля надлежащим образом.<br>
<br>
Остаётся добавить, что у меня этот способ применяется в нескольких проектах, которые непрерывно крутятся в течение недель и месяцев, и никаких проблем не возникает.<br>
<br>
P.S. Да, конечно, можно юзать классы, но по моему глубокому убеждению, класс должен уметь сам что-то делать, запись же создана исключительно для хранения данных. Кроме того, объекты не присвоишь так же легко, как записи.<br>
<br>
<span class="tag-color tag-color-named" data-value="gray" style="color: gray"><span class='tag-size' data-value='7' style='font-size:7pt;'>Эта тема была разделена из темы &quot;<a class='tag-url' href='http://forum.sources.ru/index.php?showtopic=310732' target='_blank'>Alloc/GetMem + поля записи ссылочного типа</a>&quot;</span></span>]]></description>
        <author>Fr0sT</author>
        <category>Алгоритмы</category>
      </item>
	
      </channel>
      </rss>
	