Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.12.24;
Скачать: CL | DM;

Вниз

Выделение 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]

Куда передать?



Страницы: 1 2 вся ветка

Текущий архив: 2006.12.24;
Скачать: CL | DM;

Наверх




Память: 0.57 MB
Время: 0.051 c
2-1165353601
kester
2006-12-06 00:20
2006.12.24
Опять вопрос по ReadProcessMemory


2-1165315717
Winter
2006-12-05 13:48
2006.12.24
Добавить дату в цикле


15-1165016744
ImageList1
2006-12-02 02:45
2006.12.24
Как сохранить все картинки из TImageList ?


2-1165164911
FIL-23
2006-12-03 19:55
2006.12.24
вывод только части информации из dbcombox :)


2-1165260019
funky
2006-12-04 22:20
2006.12.24
Импорт в эксель