Ошибка инициализации dll из потока памяти
Здравствуйте!
Прошу помощи. Задача следующая:
1. Необходимо получить с сервера dll и поместить ее в MemoryStream. Этот шаг проходит успешно.
2. Инициализировать dll и использовать ее функцию для расчетов. Для работы с dll из потока памяти используется модуль BTMemoryModule.
Среда разработки Delphi 7.
Ошибка возникает после приема dll, в поток памяти на стороне клиента, во время ее инициализации в строчке:
PHP код:
mp_MemoryModule := BTMemoryLoadLibary(mp_DllData, m_DllDataSize);
Ошибка следующая:
Project GVM.exe raised exception class EAccessViolation with message 'Access Violation at adress 00401D2D in module 'GMV.exe.' Write of adress 00000001'.
Тестировал в отдельном проекте там все работает безупречно, но в тестовом всего 2 формы, на одной все это дело происходит, а вторая пустая.
Выкладываю исходник модуля, где возникает ошибка, закомментил строчку, где происходит ошибка:
PHP код:
unit Initialize;
interface
uses
BTMemoryModule, Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Gauges, StdCtrls,IniFiles, ExtCtrls, jpeg,VMF, ScktComp;
type
Tvm=function (b,d:real;t:integer):double;stdcall;
TForm3 = class(TForm)
Gauge1: TGauge;
Timer1: TTimer;
Label1: TLabel;
Image1: TImage;
LabelIP_serv: TLabel;
LabelPort_serv: TLabel;
Label2: TLabel;
EditIP_serv: TEdit;
EditPort_serv: TEdit;
EditPIN_code: TEdit;
ButtonConnect: TButton;
ClientSocket1: TClientSocket;
procedure Timer1Timer(Sender: TObject);
procedure ButtonConnectClick(Sender: TObject);
procedure ClientSocket1Connect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
private
Reciving:boolean;
mem_stream1:TMemoryStream;
DataSize:integer;
public
end;
var
Form3: TForm3;
VM_func:TVMF;// объектная переменная
vm1:Tvm;
mp_DllData: Pointer; // *-vars for load dll
m_DllDataSize: Integer;
mp_MemoryModule: PBTMemoryModule; //-*
procedure load_dll(mem_stream:TMemoryStream);// процедура загрузки dll, собственно в ней и возникает ошибка
implementation
uses math_module,main;
{$R *.dfm}
procedure TForm3.Timer1Timer(Sender: TObject);
var
g:pointer;
IniFile : TIniFile;
Path:String;
start,num_points:integer;
begin
Path:=Application.ExeName;
Path:=ExtractFileDir(Path);
if Path[Length(Path)]<>'\' then Path:=Path+'';
IniFile:=TIniFile.Create(Path+'config.ini');
try
start:=StrToInt(IniFile.ReadString ('Params','Start_iniz','0'));
num_points:=StrToInt(IniFile.ReadString ('Params','Num_points','4000'));
except
end;
IniFile.Free;
Form3.Timer1.Enabled:=false;
VM_func:=TVMF.Create(1.0,2.0,1.0,2.0,start,num_points);
BTMemoryFreeLibrary(mp_MemoryModule) ;
FreeMemory(mp_DllData);
Application.CreateForm(TForm1, Form1);
G:=@Application.MainForm;
Pointer(G^) := Form1;
Form1.Show;
Form3.Free;
end;
procedure TForm3.ButtonConnectClick(Sender: TObject);
begin
ClientSocket1.Host:=Form3.EditIP_serv.Text;
ClientSocket1.Port:=StrToInt(Form3.EditPort_serv.Text);
ClientSocket1.Active:=true;
end;
procedure TForm3.ClientSocket1Connect(Sender: TObject;
Socket: TCustomWinSocket);
begin
ClientSocket1.Socket.SendText(Form3.EditPIN_code.Text);
end;
procedure TForm3.ClientSocket1Read(Sender: TObject;
Socket: TCustomWinSocket);
var
s, sl: String;
g:pointer;
begin
s:= Socket.ReceiveText;
if Reciving then
begin
mem_stream1.Write(s[1], length(s));
if mem_stream1.Size=DataSize then
begin
Reciving:=false;
load_dll(mem_stream1);
ClientSocket1.Active:=false;
Timer1.Enabled:=true;
exit;
end;
end;
if copy(s, 1, 5)='Size:' then
begin
sl:=copy(s, 6, Pos(#0, s)-6);
DataSize:=StrToInt(sl);
Delete(s, 1, Pos(#0, s));
Reciving:=true;
mem_stream1:=TMemoryStream.Create;
mem_stream1.Write(s[1], length(s));
end;
end;
// В этой процедуре возникает ошибка
procedure load_dll(mem_stream:TMemoryStream);
begin
mem_stream.Position := 0;
m_DllDataSize := mem_stream.Size;
mp_DllData := GetMemory(m_DllDataSize);
mem_stream.Read(mp_DllData^, m_DllDataSize);
mem_stream.Free;
mp_MemoryModule := BTMemoryLoadLibary(mp_DllData, m_DllDataSize);// ЗДЕСЬ ОШИБКА!
try
if mp_MemoryModule=nil then
exit;
@vm1:=BTMemoryGetProcAddress(mp_MemoryModule,'vm);
if @vm1=nil then
exit;//Функция не найдена
except
end;
end;
end.
И исходник модуля, который инициализирует запуск приложения, чтобы видели, что вообще имеется в программе:
PHP код:
program GVM;
uses
Forms,
BTMemoryModule in 'BTMemoryModule.pas',
Main in 'Main.pas' {Form1},
math_module in 'math_module.pas',
Config in 'Config.pas' {Form2},
Initialize in 'Initialize.pas' {Form3},
VMF in 'VMF.pas',
FAM in 'FAM.pas',
EvalThread in 'EvalThread.pas',
ConnectServer in 'ConnectServer.pas';
{$R *.res}
begin
Application.Initialize;
Application.Title := 'FAM Generator';
Application.CreateForm(TForm3, Form3);
Application.Run;
end.
Человеку, который поможет решить проблему заплачу 10$.
|