Форум: "Начинающим";
Текущий архив: 2006.12.24;
Скачать: [xml.tar.bz2];
ВнизВыделение PChar Найти похожие ветки
← →
Vga © (2006-12-06 11:55) [0]Возник такой вопрос. Есть функция в DLL:
Foo(...): PChar;
1) Как выделить память для результата?
2) Надо ли выполнять дополнительные действия по ее освобождению4 если да, то где и какие, если нет - то когда она будет освобождена?
← →
BiN © (2006-12-06 12:02) [1]Это зависит от реализации Foo
← →
Vga © (2006-12-06 12:04) [2]> [1] BiN © (06.12.06 12:02)
???
Я Foo и пишу. Мне надо выделить память для результата выполнения.
← →
Romkin © (2006-12-06 12:04) [3]1. Память здесь должна выделяться внутри функции. Вообще говоря, так писать вредно, потому что
2. Освобождать выделенную память должна вызывающая сторона, после использования. Как - зависит от того, как выделяется память в функции :)
В большинстве функций API сделано по другому, ты должен дать указатель на уже выделенный буфер и его размер. А результат функции - требуемый размер буфера. Это гораздо удобнее, ты выделяешь память :)
← →
Vga © (2006-12-06 12:05) [4]> [0] Vga © (06.12.06 11:55)
> освобождению4 если да, то где и какие
освобождению; если да, то где и какие
← →
Vga © (2006-12-06 12:06) [5]> [3] Romkin © (06.12.06 12:04)
Вот и у меня такие подозрения возникли... С другой стороны, мне помнится, есть в WinAPI функции, возвращающие PChar...
← →
Сергей М. © (2006-12-06 12:14) [6]
> Vga
При таком подходе (выделение памяти в вызываемом модуле, а ее освобождение - в вызывающем модуле) должно быть соблюдено соглашение об использовании взвимодействующими модулями одного и того же менеджера памяти.
И пока это соглашение явно не определено, задача не имеет решения.
← →
Romkin © (2006-12-06 12:16) [7]
> Я Foo и пишу. Мне надо выделить память для результата выполнения.
Ужас! Не пиши так! Пусть дают ссылку на буфер (см GetWindowText к примеру).
← →
Reindeer Moss Eater © (2006-12-06 12:16) [8]StrAlloc()
← →
DevilDevil © (2006-12-06 12:19) [9]> мне помнится, есть в WinAPI функции, возвращающие PChar...
Такие функции действительно есть... но они возвращают указатель на буффер, который ты указал в качестве одного из параметров этой функции. Вот такой вот WinApi-каламбур.
← →
Anatoly Podgoretsky © (2006-12-06 12:22) [10]> Vga (06.12.2006 12:05:04) [4]
Кто выделяет, тот и освобождает.
← →
Romkin © (2006-12-06 12:23) [11]
> Reindeer Moss Eater © (06.12.06 12:16) [8]
>
> StrAlloc()
Угу. И типа всем сразу юзать strDispose?!
Ну ты посоветуешь! Это же менеджер памяти Delphi, во-первых, а во-вторых, функции устарели.
На крайняк GlobalAlloc тогда уж.
← →
Anatoly Podgoretsky © (2006-12-06 12:23) [12]> Vga (06.12.2006 12:06:05) [5]
Большинство не возвращают, а использую выданный тобой буфер, с указанием размера или без.
← →
clickmaker © (2006-12-06 12:26) [13]Если функция возвращает уже распредленный в памяти буфер, то эта же ДЛЛ может предоставить функцию для ее освобождения. Как это сделано в НетАПИ - NetApiBufferFree
← →
Romkin © (2006-12-06 12:34) [14]clickmaker © (06.12.06 12:26) [13] Или обусловить, какой именно функцией надо освобождать буфер. (SHGetSpecialFolderLocation, например, но, к сожалению, в SDK Delphi нужной фразы и нет :( )
Обычно это - в случае сложной структуры буфера.
А для PChar проще всего попросить приложение предоставить буфер. Мне, например, удобно - дал вместо ссылки на буфер nil, размер указал 0, возвращает требуемый размер - выделяем память и вызываем снова :)
← →
Vga © (2006-12-06 12:42) [15]В общем понятно... Либо надо предоставлять функцию освобождения строки, либо возвращать ссылку на данные, которые будут верны все время, пока с ними работает вызывающая сторона (например, константу), либо не возвращать PChar.
← →
Reindeer Moss Eater © (2006-12-06 12:46) [16]Угу. И типа всем сразу юзать strDispose?!
Ну ты посоветуешь! Это же менеджер памяти Delphi, во-первых, а во-вторых, функции устарели.
На крайняк GlobalAlloc тогда уж.
Если отвлечься от вопроса, то я бы вообще посоветовал не создавать такие откровенно корявые функции.
function myfunc : PChar
Но раз уж она есть в вопросе, то вылделять память все равно надо, или функция эта бесполезна будет. Если только она не выполняет какое-нибудь бестолковое действие типа
Result := PChar(caption)
← →
Reindeer Moss Eater © (2006-12-06 12:48) [17]Кстати, каким местом устарела страллок?
function StrAlloc(Size: Cardinal): PChar;
begin
Inc(Size, SizeOf(Cardinal));
GetMem(Result, Size);
Cardinal(Pointer(Result)^) := Size;
Inc(Result, SizeOf(Cardinal));
end;
← →
DevilDevil © (2006-12-06 12:51) [18]
> Reindeer Moss Eater © (06.12.06 12:48) [17]
>
> Кстати, каким местом устарела страллок?
GetMem - это функция, которая задействует Дельфийский менеджер памяти. Отсюда несовместимость.
← →
Vga © (2006-12-06 12:51) [19]> Но раз уж она есть в вопросе, то вылделять память все равно
> надо, или функция эта бесполезна будет. Если только она
> не выполняет какое-нибудь бестолковое действие типа
> Result := PChar(caption)
Вот это-то как раз пример, когда используется именно такая функция, так как никакой памяти выделять не надо. И насчет бестолковости действия вопрос спорный - иногда использующей стороне надо предоставить возможность чтения некоторых данных библиотеки.
← →
Vga © (2006-12-06 12:55) [20]Если ставить цель сохранить именно такое объявление, то можно выделить для возврата данных глобальную переменную, класть результат в нее и возвращать на нее ссылку, освобождать при финализации. Но это решение через то самое место :) К тому же, придется документировать, до каких пор результат содержит корректные данные, а доки не все читают... Однако решение с выделением буфера на вызывающей стороне тоже не очень хорошо, так как процесс получения результата (а следовательно и его длины) довольно продолжительный...
← →
Anatoly Podgoretsky © (2006-12-06 12:55) [21]> Vga (06.12.2006 12:42:15) [15]
Или что чаще всего делается, передавать этот буфер в функцию.
← →
Anatoly Podgoretsky © (2006-12-06 12:56) [22]> Vga (06.12.2006 12:51:19) [19]
Это тот случай, когда память выделять не надо, долго живущие данные. Такие есть и в АПИ
← →
Vga © (2006-12-06 12:58) [23]> [21] Anatoly Podgoretsky © (06.12.06 12:55)
Этот вариант входит в
> либо не возвращать PChar.
← →
Reindeer Moss Eater © (2006-12-06 12:59) [24]GetMem - это функция, которая задействует Дельфийский менеджер памяти. Отсюда несовместимостьи
Это не имеет значения.
1. Функция DLL написанная нечайником, никогда не распределит память сама, а скажет какой длины буфер ей надо что бы вернуть данные.
2. Если я узнал длину буфера, и у меня скажем нет переменной string которй я могу сделать setlength, то чем таким страшным устарела страллок, если я не собираюсь передвать ссылку ни в какой другой процесс?
← →
Anatoly Podgoretsky © (2006-12-06 13:00) [25]> Vga (06.12.2006 12:55:20) [20]
Поэтому таких в АПИ считаное количество, большинство функций АПИ ни таким, ни выделением не занимается, а использует буфер пользователя. Некоторые могут сообщить, какой по размеру требуется.
← →
Anatoly Podgoretsky © (2006-12-06 13:04) [26]> Vga (06.12.2006 12:58:23) [23]
Почему бы и нет, посмотри в справке функции работы с PChar многие из них возвращают как результат. Возвращение как результат позволяет использовать эту функцию в качестве параметра другой функции.
Твой вопрос без постановки задачи ничего не стоит.
Сначала надо поставить задачу, правда тогда и вопроса не будет.
← →
Vga © (2006-12-06 13:05) [27]Спасибо, свою ошибку я понял... Теперь надо думать, как реализовать... Склоняюсь к методу из [20] по причине удобства вызывающей стороны, так как результат обычно используется сразу, а если не так - можно скопировать.
Метод с передачей буфера не хотелось бы, так как функция не из быстрых, и вызывать два раза не хотелось бы...
← →
DevilDevil © (2006-12-06 13:06) [28]
> Vga ©
А у тебя буфер переменной длинны?
Как вариант: в хедере к Dll, в implementation пусть статически будет лежать буфер. ПРи инициализации Dll, в Dll передаётся указатель на этот буфер. Соответственно, проблем с извлечением данных из буфера не будет.
← →
Vga © (2006-12-06 13:07) [29]> [26] Anatoly Podgoretsky © (06.12.06 13:04)
Вопрос довольно общий, навеяно конкретным случаем, из-за которого и возникли [20], [27], но я хотел получить информацию, которую можно использовать в других случаях, когда надо вернуть строковые данные. Такую информацию получил, спасибо всем.
← →
Reindeer Moss Eater © (2006-12-06 13:08) [30]Склоняюсь к методу из [20]
такое же корявое решение.
DLL вернув результат не должна париться над вопросом как долго вызывающее приложение будет юзать ссылку.
А приложение не должно париться можно ли менять содержимое по ссылке и вообще как долго будет живо содержимое этого буфера.
← →
Vga © (2006-12-06 13:11) [31]> [30] Reindeer Moss Eater © (06.12.06 13:08)
В общем случае. А частный я не описал, да и не буду, сам уже разобрался, так что [20] надо рассматривать как частный случай решения с ограниченной применимостью. Он ведь рабочий и при соблюдении ограничений вполне корректный.
← →
Anatoly Podgoretsky © (2006-12-06 13:21) [32]> Vga (06.12.2006 13:05:27) [27]
Можно вызывать только один раз, выдели буфер достаточного размера.
← →
Anatoly Podgoretsky © (2006-12-06 13:22) [33]> Vga (06.12.2006 13:11:31) [31]
Вопрос последний, а нужен ли PChar - для Дельфи не требуется, это если только извне, вин апи, user dll
← →
Vga © (2006-12-06 13:26) [34]> [33] Anatoly Podgoretsky © (06.12.06 13:22)
Требуется. Но это уже не по теме.
← →
app © (2006-12-06 13:31) [35]Ну почему не по теме, если не нужны, то тема сразу закрывается по причине отсутствия в необходимости.
Для справки string полностью совместим с PChar
← →
Vga © (2006-12-06 13:35) [36]> [35] app © (06.12.06 13:31)
Вопрос был, как передать именно PChar, точнее, языконезависимый строковый тип. Если бы ansistring подходили всегда и везде, вопроса бы и не возникло.
← →
Vga © (2006-12-06 13:38) [37]А учитывая, что ответ я получил, то можно тему и закрыть, ничего не имею против.
← →
app © (2006-12-06 13:39) [38]Ты не понял, не физически закрыть, а по причине отсутсвия вопроса.
← →
Vga © (2006-12-06 13:41) [39]> [38] app © (06.12.06 13:39)
Вопрос есть, но "нужен ли PChar" - вопрос вне темы, т.к. я спрашивал именно про PChar.
← →
Anatoly Podgoretsky © (2006-12-06 13:53) [40]> Vga (06.12.2006 13:35:36) [36]
Куда передать?
← →
Vga © (2006-12-06 14:03) [41]> [40] Anatoly Podgoretsky © (06.12.06 13:53)
Из функции (в dll) в вызывающую процедуру.
← →
Romkin © (2006-12-06 14:09) [42]Reindeer Moss Eater © (06.12.06 12:59) [24] F1 нажимал? Читал, что написано про StrAlloc? Только для обратной совместимости. Вместо нее давно уже ansistring тип есть.
И если ты думаешь, что выделив StrAlloc память в dll ты можешь легко освободить ее StrDispose в основном приложении - флаг в руки, барабан на шею - тоннель сам найдешь. Тут нужно использовать внешний менеджер памяти, точно как в случае с длинными строками. Со всеми вытекающими.
Страницы: 1 2 вся ветка
Форум: "Начинающим";
Текущий архив: 2006.12.24;
Скачать: [xml.tar.bz2];
Память: 0.56 MB
Время: 0.046 c