Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Выделение PChar


Страницы:   1 2 3

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 сделано по другому, ты должен дать указатель на уже выделенный буфер и его размер. А результат функции -  требуемый размер буфера. Это гораздо удобнее, ты выделяешь память :)


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо