Проблема в том, что вы изменяете адрес, содержащийся в переменной ptr.
Вы вызываете AllocMem для выделения буфера, на который вы ссылаетесь, используя ptr. Это хорошо. Но вы никогда не должны изменять значение ptr, адрес буфера. И вы его меняете.
Вы писали:
ptr:=AllocMem(40);
ptr:=Pchar('OneNationUnderGod');
Вторая строка является проблемой. Вы изменили ptr, и теперь ptr ссылается на что-то другое (строковый литерал, хранящийся в постоянной памяти, когда это происходит). Теперь вы потеряли следы буфера, выделенного вашим вызовом AllocMem. Вы спросили AllocMem о новом блоке памяти и сразу же отбросили этот блок памяти.
Что вы, по-видимому, хотите сделать, это скопировать строку. Возможно, как это:
ptr := AllocMem(40);
StrCopy(ptr, 'OneNationUnderGod');
Теперь мы прекрасно назвать FreeMem, потому что PTR по-прежнему содержит адрес, что вызов AllocMem предусмотрено.
ptr := AllocMem(40);
try
StrCpy(ptr, 'OneNationUnderGod');
// do stuff with ptr
finally
FreeMem(ptr);
end;
Очевидно, что в реальном коде вы бы найти лучший и более надежный способ определения длины буфера, чем жестко кодированные значения.
В вашем коде, при условии, что указанное исправление применяется, тест на ptr, являющийся нолем, бесполезен. AllocMem никогда не возвращает ниль. Отказ AllocMem приводит к возникновению исключения.
Сказав все это, обычным способом работать с строковыми буферами обычно нет. Нормально использовать строки Delphi. Если вам нужен PChar, например, для использования с interop, сделайте одно с PChar (str), где str имеет строку типа.
Вы говорите, что вы должны использовать динамически распределенные буферы PChar. Возможно, это так, но я очень сомневаюсь в этом.
AFAIR в Delphi, который является strcOpy ;-) и, возможно, StrLCopy будет еще более надежным шаблоном вообще –
@ Arioch'The Спасибо за исправление. StrLCopy может быть хорошим. Но я думаю, что всегда использовал строку и PChar(). StrCopy иногда отлично, если вы выделяете правильный размер буфера. Если вы вызвали StrLen, то Move - как я это сделаю. –
Нет, я просто вижу StrLCopy как предел безопасности, сразу после выделения, такого как AllocMem (const) выше. После преобразования большого количества кода, например move (x, y, sizeof (y)) в Unicode :-D –