![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Выделение PChar
Vga © (2006-12-06 11:55:00)Возник такой вопрос. Есть функция в DLL:
Foo(...): PChar;
1) Как выделить память для результата?
2) Надо ли выполнять дополнительные действия по ее освобождению4 если да, то где и какие, если нет - то когда она будет освобождена?
Anatoly Podgoretsky (2006-12-06 12:56:00) [21]> Vga (06.12.2006 12:51:19) [19]
Это тот случай, когда память выделять не надо, долго живущие данные. Такие есть и в АПИ
Anatoly Podgoretsky (2006-12-06 12:55:00) [22]> Vga (06.12.2006 12:42:15) [15]
Или что чаще всего делается, передавать этот буфер в функцию.
Vga (2006-12-06 12:55:00) [23]Если ставить цель сохранить именно такое объявление, то можно выделить для возврата данных глобальную переменную, класть результат в нее и возвращать на нее ссылку, освобождать при финализации. Но это решение через то самое место :) К тому же, придется документировать, до каких пор результат содержит корректные данные, а доки не все читают... Однако решение с выделением буфера на вызывающей стороне тоже не очень хорошо, так как процесс получения результата (а следовательно и его длины) довольно продолжительный...
Vga (2006-12-06 12:51:00) [24]> Но раз уж она есть в вопросе, то вылделять память все равно
> надо, или функция эта бесполезна будет. Если только она
> не выполняет какое-нибудь бестолковое действие типа
> Result := PChar(caption)
Вот это-то как раз пример, когда используется именно такая функция, так как никакой памяти выделять не надо. И насчет бестолковости действия вопрос спорный - иногда использующей стороне надо предоставить возможность чтения некоторых данных библиотеки.
DevilDevil (2006-12-06 12:51:00) [25]
> Reindeer Moss Eater © (06.12.06 12:48) [17]
>
> Кстати, каким местом устарела страллок?
GetMem - это функция, которая задействует Дельфийский менеджер памяти. Отсюда несовместимость.
Reindeer Moss Eater (2006-12-06 12:48:00) [26]Кстати, каким местом устарела страллок?
function StrAlloc(Size: Cardinal): PChar;
begin
Inc(Size, SizeOf(Cardinal));
GetMem(Result, Size);
Cardinal(Pointer(Result)^) := Size;
Inc(Result, SizeOf(Cardinal));
end;
Reindeer Moss Eater (2006-12-06 12:46:00) [27]Угу. И типа всем сразу юзать strDispose?!
Ну ты посоветуешь! Это же менеджер памяти Delphi, во-первых, а во-вторых, функции устарели.
На крайняк GlobalAlloc тогда уж.
Если отвлечься от вопроса, то я бы вообще посоветовал не создавать такие откровенно корявые функции.
function myfunc : PChar
Но раз уж она есть в вопросе, то вылделять память все равно надо, или функция эта бесполезна будет. Если только она не выполняет какое-нибудь бестолковое действие типа
Result := PChar(caption)
Vga (2006-12-06 12:42:00) [28]В общем понятно... Либо надо предоставлять функцию освобождения строки, либо возвращать ссылку на данные, которые будут верны все время, пока с ними работает вызывающая сторона (например, константу), либо не возвращать PChar.
Romkin (2006-12-06 12:34:00) [29]clickmaker © (06.12.06 12:26) [13] Или обусловить, какой именно функцией надо освобождать буфер. (SHGetSpecialFolderLocation, например, но, к сожалению, в SDK Delphi нужной фразы и нет :( )
Обычно это - в случае сложной структуры буфера.
А для PChar проще всего попросить приложение предоставить буфер. Мне, например, удобно - дал вместо ссылки на буфер nil, размер указал 0, возвращает требуемый размер - выделяем память и вызываем снова :)
clickmaker (2006-12-06 12:26:00) [30]Если функция возвращает уже распредленный в памяти буфер, то эта же ДЛЛ может предоставить функцию для ее освобождения. Как это сделано в НетАПИ - NetApiBufferFree
Anatoly Podgoretsky (2006-12-06 12:23:00) [31]> Vga (06.12.2006 12:06:05) [5]
Большинство не возвращают, а использую выданный тобой буфер, с указанием размера или без.
Romkin (2006-12-06 12:23:00) [32]
> Reindeer Moss Eater © (06.12.06 12:16) [8]
>
> StrAlloc()
Угу. И типа всем сразу юзать strDispose?!
Ну ты посоветуешь! Это же менеджер памяти Delphi, во-первых, а во-вторых, функции устарели.
На крайняк GlobalAlloc тогда уж.
Anatoly Podgoretsky (2006-12-06 12:22:00) [33]> Vga (06.12.2006 12:05:04) [4]
Кто выделяет, тот и освобождает.
DevilDevil (2006-12-06 12:19:00) [34]> мне помнится, есть в WinAPI функции, возвращающие PChar...
Такие функции действительно есть... но они возвращают указатель на буффер, который ты указал в качестве одного из параметров этой функции. Вот такой вот WinApi-каламбур.
Reindeer Moss Eater (2006-12-06 12:16:00) [35]StrAlloc()
Romkin (2006-12-06 12:16:00) [36]
> Я Foo и пишу. Мне надо выделить память для результата выполнения.
Ужас! Не пиши так! Пусть дают ссылку на буфер (см GetWindowText к примеру).
Сергей М. (2006-12-06 12:14:00) [37]
> Vga
При таком подходе (выделение памяти в вызываемом модуле, а ее освобождение - в вызывающем модуле) должно быть соблюдено соглашение об использовании взвимодействующими модулями одного и того же менеджера памяти.
И пока это соглашение явно не определено, задача не имеет решения.
Vga (2006-12-06 12:06:00) [38]> [3] Romkin © (06.12.06 12:04)
Вот и у меня такие подозрения возникли... С другой стороны, мне помнится, есть в WinAPI функции, возвращающие PChar...
Vga (2006-12-06 12:05:00) [39]> [0] Vga © (06.12.06 11:55)
> освобождению4 если да, то где и какие
освобождению; если да, то где и какие
Romkin (2006-12-06 12:04:00) [40]1. Память здесь должна выделяться внутри функции. Вообще говоря, так писать вредно, потому что
2. Освобождать выделенную память должна вызывающая сторона, после использования. Как - зависит от того, как выделяется память в функции :)
В большинстве функций API сделано по другому, ты должен дать указатель на уже выделенный буфер и его размер. А результат функции - требуемый размер буфера. Это гораздо удобнее, ты выделяешь память :)