Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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
11-1130485465
nester
2005-10-28 11:44
2006.12.24
Как в EditBox заменить символ для ввода пароля?


15-1165266043
Cerberus
2006-12-05 00:00
2006.12.24
Почему возникает ошибка при попытке чтения блока.


15-1165164998
ANTPro
2006-12-03 19:56
2006.12.24
Проблема с винтом


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


2-1165237693
Steep
2006-12-04 16:08
2006.12.24
Opengl





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский