Текущий архив: 2004.08.22;
Скачать: CL | DM;
Вниз
Передача строк в/из функции dll Найти похожие ветки
← →
Aldor_ (2004-08-06 15:41) [0]В функцию из одной из стандартных библиотек windows в качестве выходного параметра должна передаваться структура, содержащая указатели на строки.
В описании параметра написано слелующее:Strings returned by InternetQueryOption are globally allocated, so the calling application must free them when it is finished using them
.
Это что же получается, ОН(она) память выделяет, а Я должен ее освобождать?!
Что означает globally allocated?
Под саму структуру (в том числе и указатели на строки) память выделять и освобождать мне?
И что передавать в качестве размера буфера?
← →
TUser © (2004-08-06 15:59) [1]В WinAPI-функции обычно передается PChar (точнее - PAnsiChar). Я тут на форуме недавно с этим разбирался. Если ф-ция должна вернуть что-то в этот буфер, то память надо выделить (размер буфера - максимальный по твоим представлениям размер результата), а потом освободить. Если же ты передаешь строку в апи-функцию (как, например, в FindWindow), то синтаксис такойже, как при работе с обычными строками, а за выделением/освобождением памяти следит компилятор (точнее - менеджер памяти).
← →
VMcL © (2004-08-06 16:10) [2]>>Aldor_ (06.08.04 15:41)
GlobalFree(), я полагаю.
← →
Aldor_ (2004-08-06 16:12) [3]TUser © (06.08.04 15:59) [1]
Пробовал делать так:
(* TInternetProxyInfo = record
dwAccessType: DWORD;
lpszProxy: LPCSTR;
lpszProxyBypass: LPCSTR;
end; *)
const
MaxStrSize: Cardinal = 1024;
var
ProxyInfo: PInternetProxyInfo;
StructSize: Cardinal;
begin
StructSize := SizeOf(TInternetProxyInfo);
GetMem(ProxyInfo, StructSize);
try
GetMem(ProxyInfo^.lpszProxy, MaxStrSize);
try
Inc(StructSize, MaxStrSize);
InternetQueryOption(nil, INTERNET_OPTION_PROXY, ProxyInfo, StructSize);
finally
FreeMem(ProxyInfo^.lpszProxy);
end;
ShowMessage(ProxyInfo^.lpszProxy);
finally
FreeMem(ProxyInfo);
end;
На выделенной строке значение ProxyInfo^.lpszProxy МЕНЯЕТСЯ! То есть функция сама присваевает этим указателям какие-то значения, а значит и сама выделят пямять под строки.
P.S. Естественно, на FreeMem(ProxyInfo^.lpszProxy); вылетает AV
← →
VMcL © (2004-08-06 16:12) [4]>>VMcL © (06.08.04 16:10) [2]
Хотя нет. Обманул. Вот пример из MSDN:DWORD dwSize;
// This call determines the buffer size needed.
InternetQueryOption(NULL,INTERNET_OPTION_USER_AGENT,NULL,&dwSize);
// Allocate the necessary memory.
lpszData = new char[dwSize];
// Call InternetQueryOption again with the buffer provided.
InternetQueryOption(NULL, INTERNET_OPTION_USER_AGENT,lpszData,&dwSize);
// Insert code to user the user agent string information.
// Free the allocated memory.
delete [] lpszData;
В общем, сам буфер выделяешь, сам и освобождаешь.
← →
Aldor_ (2004-08-06 16:15) [5]VMcL © (06.08.04 16:10) [2]
> GlobalFree(), я полагаю.
Там параметром стоит:
HGLOBAL hMem
[in] Handle to the global memory object. This handle is returned by either the GlobalAlloc or GlobalReAlloc function.
Функция InternetQueryOption этот HGLOBAL не возвращает.
← →
VMcL © (2004-08-06 16:18) [6]Надо же. И всё таки я был прав в [2].
Retrieving Connection Options
Beginning with Internet Explorer 5, Internet options can be retrieved from a specific connection. To retrieve options from a particular connection, complete the following steps:
Create a INTERNET_PER_CONN_OPTION_LIST structure.
Allocate the memory for the individual Internet options that you want to retrieve from the connection.
Specify the options using INTERNET_PER_CONN_OPTION structures.
Retrieve the options using InternetQueryOption.
Utilize the option information.
Free the memory that was allocated to hold the option information using the GlobalFree function.
← →
VMcL © (2004-08-06 16:19) [7]>>Aldor_ (06.08.04 16:15) [5]
Приведение типов отменили?
← →
Aldor_ (2004-08-06 16:19) [8]VMcL © (06.08.04 16:12) [4]
InternetQueryOption(NULL,INTERNET_OPTION_USER_AGENT,NULL,&dwSize);
Функция с ЭТИМ параметром возвращает всего лишь строку, а с INTERNET_OPTION_PROXY возвразает структуру TInternetProxyInfo (описана в [3])
Кстати, вы где примерчик взяли? Я там не нашел...
← →
Aldor_ (2004-08-06 16:26) [9]VMcL © (06.08.04 16:19) [7]
Пока один отвечает, другой уже запостить успевает :)
[6]:
Да, читал но не разобрался, понял вот так:
Память под структуру выделяю и освобождаю сам (GetMem/FreeMem)
Память под строки выделяет функция, но освобождаю я сам с помощьюGlobalFree(HGLOBAL(PointerToString))
Правильно?
← →
VMcL © (2004-08-06 16:35) [10]>>Aldor_ (06.08.04 16:26) [9]
>Правильно?
А Гейтс его знает. Почитай в справке. Там примеры есть. А вообще, как любит говорить Игорь Шевченко, "практика - критерий истины".
← →
Aldor_ (2004-08-06 16:43) [11]Спасибо за помощь!
← →
Aldor_ (2004-08-07 15:11) [12]Провел маленькое исследование.
Если вызывать функцию в таком виде:InternetQueryOption(nil, INTERNET_OPTION_PROXY, ProxyInfo, StructSize);
Строка (ProxyInfo^.lpszProxy) пишется по адресу ProxyInfo + SizeOf(TInternetProxyInfo), т.е. внагляк сразу после структуры по стеку.
Освободить память при помощи GlobalFree(HGLOBAL(ProxyInfo^.lpszProxy)) не получилось, как и следовало ожидать, это некорретное преобразование.
Работающим (но не факт что корректным) вариантом оказался такой:
StructSize := SizeOf(TInternetProxyInfo) + MaxStrSize;
GetMem(ProxyInfo, StructSize);
try
if not InternetQueryOption(nil, INTERNET_OPTION_PROXY, ProxyInfo, StructSize) then
RaiseLastOSError;
ShowMessage(ProxyInfo^.lpszProxy);
finally
FreeMem(ProxyInfo);
end;
Таким образом избавляемся от "локальных" накладок, но, возможно, "глобально" эта память все еще считается занятой.
Буду благодарен, если кто подскажет корректный вариант глобального освобождения памяти.
← →
VMcL © (2004-08-08 12:11) [13]>>Aldor_ (07.08.04 15:11) [12]
>Таким образом избавляемся от "локальных" накладок, но, возможно, "глобально" эта память все еще считается занятой.
Не считается. Если посмотришь в Watch, то ProxyInfo^.lpszProxy указывает как раз на область памяти сразу за структурой INTERNET_PROXY_INFO, которую ты предусмотрительно резеревируешь с помощью MaxStrSize. Только, чтобы не "угадывать" MaxStrSize, следует писать так:procedure TForm1.Button1Click(Sender: TObject);
var
StructSize: DWORD;
ProxyInfo: PInternetProxyInfo;
begin
StructSize := 0;
if not InternetQueryOption(nil, INTERNET_OPTION_PROXY, nil, StructSize) then
if GetLastError <> ERROR_INSUFFICIENT_BUFFER then RaiseLastOSError;
GetMem(ProxyInfo, StructSize);
try
if not InternetQueryOption(nil, INTERNET_OPTION_PROXY, ProxyInfo, StructSize) then
RaiseLastOSError;
ShowMessage(ProxyInfo^.lpszProxy);
finally
FreeMem(ProxyInfo);
end;
end;
← →
Aldor. (2004-08-08 15:09) [14]VMcL © (08.08.04 12:11) [13]
> ProxyInfo^.lpszProxy указывает как раз на область памяти сразу за структурой INTERNET_PROXY_INFO
Почему это является признаком того, что память не считается занятой "глобально"?
> Только, чтобы не "угадывать" MaxStrSize, следует писать так:
Угу, так точно, то был черновой вариант.
← →
VMcL © (2004-08-08 16:56) [15]>>Aldor. (08.08.04 15:09) [14]
>Почему это является признаком того, что память не считается занятой "глобально"?
Потому что ты сам её выделил GetMem"ом.
Страницы: 1 вся ветка
Текущий архив: 2004.08.22;
Скачать: CL | DM;
Память: 0.49 MB
Время: 0.031 c