Форум: "Сети";
Текущий архив: 2005.11.20;
Скачать: [xml.tar.bz2];
ВнизПроблема с idHTTP Найти похожие ветки
← →
DVladimir (2005-08-03 03:15) [0]Приветствую!
Возникла странная проблема:
взял кусок кода из модуля idHTTP, вставил в свою библиотеку - а он не работает. Кусок наипростейший, но тем не менее.
Чтобы было всё предельно понятно, привожу вызов неработающей функции и библиотеку, в которой функция описана:
--Вызов: ---
Var Content, buf: PChar;
TestProc: function: PChar;
DLLHandle: THandle;
......
DLLHandle:=LoadLibrary("libTest");
if(DLLHandle = 0) then Begin
ShowMessage("Cannot load DDL");
Application.Terminate;
end;
try
@TestProc:=GetProcAddress(DLLHandle,PChar("GetURL"));
try
buf:=TestProc;
//Предполагаю, что buf не nil (так оно есть) - проверку опущу
GetMem(Content, Length(buf)+1);
Content:=StrLCopy(Content,buf,Length(buf));
ShowMessage(StrPas(Content));
except
ShowMessage("Error in GetURL"); //Вот эта ошибка вылетает
Application.Terminate;
end;
finally
FreeLibrary(DLLHandle);
end;
--Библиотека: ---
library libTest;
uses
SysUtils,
Classes,
Dialogs, //Just for ShowMessage()
idHTTP;
{$R *.res}
function GetURL: PChar;
Var
HTTP: TidHTTP;
strResponse: TMemoryStream;
b: String;
Begin
HTTP:=TidHTTP.Create(nil);
HTTP.Host:="localhost";
HTTP.Port:=80;
strResponse:=TMemoryStream.Create;
{$H+} //For ANSI string...
try
HTTP.Connect(-1);
HTTP.DoRequest(hmGet, "http://localhost/test.html", nil, strResponse);
if strResponse.Size > 0 then begin
ShowMessage("Readed: "+IntToStr(a));
try
SetLength(b,strResponse.Size); //Вот тут если руками прописать около 1000 байт, ошибки не бывает
Move(PChar(strResponse.Memory)^, b[1],strResponse.Size);
except
//Ни одно из перечисленных exception-ов не возникает.
//Вернее блок exception вообще не выполняется
on E: EOutOfMemory do ShowMessage("E: "+E.Message);
on E: EInvalidPointer do ShowMessage("E: "+E.Message);
on E: EAccessViolation do ShowMessage("E: "+E.Message)
else ShowMessage("Unknown error");
end;
end;
Result:=PChar(b);
except
Result:=PChar("Error: "+IntToStr(HTTP.ResponseCode));
end;
strResponse.Free;
HTTP.Disconnect;
HTTP.Destroy;
end;
exports
GetURL;
begin
end.
Помогите найти ошибку!
Спасибо!
← →
Lamer@fools.ua © (2005-08-03 07:16) [1]>
Result:=PChar(b);
Это неправильно. После выхода из функции указатель станет невалидным.
← →
DVladimir (2005-08-03 13:08) [2]Да нет.
Т.е. если я пишу
SetLength(b,500); //Вот тут если руками прописать около 1000 байт, ошибки не бывает
Move(PChar(strResponse.Memory)^, b[1],500);
То вызывающая функция получает указатель на 500 байт полученного текста. И вот это
GetMem(Content, Length(buf)+1);
Content:=StrLCopy(Content,buf,Length(buf));
ShowMessage(StrPas(Content));
прекрасно отрабатывает.
← →
Digitman © (2005-08-03 13:21) [3]
> DVladimir (03.08.05 13:08) [2]
> Да нет.
да ДА !!
причем здесь "около 1000 байт" ?
время жизни лок.переменной процедуры равно времени жизни процедуры !
← →
Slym © (2005-08-03 14:30) [4]
function GetURL(Buf:PChar;SizeBuf:integer): LongBool;
Var
Response: TMemoryStream;
HTTP: TidHTTP;
Begin
try
Response:=TMemoryStream.Create;
try
HTTP:=TidHTTP.Create(nil);
try
HTTP.Get("http://localhost/test.html", Response);
if Response.Size>0 then
begin
ShowMessage("Readed: "+IntToStr(Response.Size));
StrLCopy(Buf,Response.Memory,SizeBuf-1);
end else
if SizeBuf>0 then
Buf^:=#0;
finally
HTTP.Free;
end;
finally
Response.Free;
end;
result:=true;
except
on E:Exception do
begin
result:=false;
StrLCopy(Buf,PChar(Format("Raised exception %s with message %s",[E.ClassName,E.Message])),SizeBuf-1);
end;
end;
end;
TestProc:=GetProcAddress(DLLHandle,PChar("GetURL"));
GetMem(Content, 1024);
try
TestProc(Content, 1024);
ShowMessage(StrPas(Content));
finally
FreeMem(Content);
end;
← →
DVladimir (2005-08-03 17:09) [5]Digitman © (03.08.05 13:21) [3]
Это-то да.
Не могу спорить, т.к. понимаю, что скорее всего не прав.
Скажу лишь в оправдание, что мне привычнее такое поведение:
sub MyProc {
my $a = "Some data";
return \$a;
}
и после вызова
my $ref_a = MyProc();
я получу не мертвый указатель, а именно указатель на "Some data";
Это на самом деле мой чуть ли не первый опыт на Delphi.
Тем не мнее спасибо большое!
← →
DVladimir (2005-08-03 17:44) [6]Slym © (03.08.05 14:30) [4]
Да, всё четко и понятно.
Спасибо большое!
Только вопрос несколько уже офф-топик.
Имеет ли смысл вызов
Response:=TMemoryStream.Create;
оборачивать в try ... except ?
Ну в смысле я не знаю какие могут исключения возникнуть...
← →
Digitman © (2005-08-04 08:38) [7]
> мне привычнее такое поведение
не путай.
это совсем другой случай.
> Имеет ли смысл вызов
> Response:=TMemoryStream.Create;
> оборачивать в try ... except ?
исключение при конструировании этого объекта весьма маловероятно.
например, может возникнуть EOutOfMemory, если на этот момент ты опустошил кучу
← →
Slym © (2005-08-04 09:06) [8]Для новичков ВСЕГДА имеет смысл.
Это "ручной" SafeCall - ДЛЛ должна сама обработать все ошибки! и в лучшем случае вернуть true/false в худшем код ошибки для дальнейшего анализа в программе
← →
DVladimir (2005-08-04 16:35) [9]Ага, почти всё понял. Спасибо!
Возникла еще проблема :) Прошу извинения, если достал.
Я решил в функцию не передавать BufSize, т.к. реально его размер я не знаю до получения страницы. Сделал так:
try
HTTP:=TidHTTP.Create(nil);
try
HTTP.Get("http://localhost/test.html", Response);
if Response.Size>0 then
begin
ShowMessage("Readed: "+IntToStr(Response.Size));
GetMem(Buf,Response.Size); //+1 ли?
StrLCopy(Buf,Response.Memory,Response.Size-1);
end else
Buf^:=#0;
finally
HTTP.Free;
end;
finally
Response.Free;
end;
И после GetMem у меня размер Buf становится = 3, а после StrLCopy в нем какие-то странные 3 байта.
Я даже попробовал в этой функции объявить локальную
test: PChar, так и после
GetMem(test,Response.Size);
обнаруживаю, что Length(test) равно 3.
Что я опять не так делаю, в чем не прав?
Спасибо!
← →
Slym © (2005-08-04 17:04) [10]обнаруживаю, что Length(test) равно 3.
Мдя... Ацес Виолатион по тебе плачет...
GetMem(Buf,Response.Size+1); //+1 ли? - Именно!
с PChar так "Length(test)" не поступают
Страницы: 1 вся ветка
Форум: "Сети";
Текущий архив: 2005.11.20;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.062 c