![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
передача PChar в DLL [D5, WinXP]
RWolf © (2007-03-11 10:38:00)Сижу сейчас за кодом и откровенно не соображаю, в чем дело. Программа вызывает экспортированную функцию в DLL, вот так:
TServerState=procedure(address,code,title:PChar;const info,players:array of PChar);stdcall;
...
plugin.ServerState(PChar(address),PChar(game.Code),PChar(game.Title),pcinfo,pcpl ayers);
В DLL функция делает следующее:
procedure ServerState(address,code,title:PChar;const info,players:array of PChar);stdcall;
var s1,s2,s3:String;
...
try
s1:=address;
s2:=code; // <---
s3:=title;
...
except
on e:Exception do flog(e.Message);
end;
в строчке, отмеченной комментарием, судя по логу, иногда возникает Access violation ... Write of address 10018027.
Собственно, хотелось бы узнать причину, поэтому вопрос такой: корректна ли такая передача параметров в DLL? может, я чего важного не знаю насчет дельфовского менеджера памяти?
trubin (2007-03-11 21:11:00) [1]
> var
> game:PGameDefs; //заполняется при старте
А как заполняется?
Если примерно так:
procedureStartProc;
var
s: string;
begin
s:= 'qwerty';
game.Code:= PChar(s);
end;
то понятно: т.к. stringтип с управляемым временем жизни, и к моменту вызова ф-ии из ДЛЛ-ки по адресу game.Code может быть AV. Уж как повезет.
Для game.Code надо выделять память, и потом не забыть ее освободить.
RWolf (2007-03-11 19:11:00) [2]Переписал, и что бы вы думали? глюк не исчез :)
Теперь вызов выглядит так:
TServerState=procedure(address:PChar; game:PGameDefs;
nInfo:Integer; info:PChar;
nPlayers:Integer;names:PChar;frags:PInteger
);stdcall;
TGameDefs=record
Code: PChar;
...
end;
PGameDefs=^TGameDefs;
var
game:PGameDefs; //заполняется при старте
...
plugin.ServerState(
PChar(address),game,
Length(info),PChar(plug_info),
players.Count,PChar(plug_players),PInteger(plug_frags));
Плагин:
procedure ServerState(address:PChar; game:PGameDefs;
nInfo:Integer; info:PChar;
nPlayers:Integer;names:PChar;frags:PInteger);stdcall;
...
s1:=address;
s2:=game.Code; //здесь AV через произвольное число вызовов
Было замечено следующее. Далее плагин передает строчку s2 функции, которая вызывает TDataset.Locate:
procedure GameLocate(const gametype:string);
begin
Form1.fdGames.Locate('GAMETYPE',string(gametype),[loCaseInsensitive]);
...
end;
Приведение к string оставалось с того времени, когда параметр имел тип PChar; по идее, от приведения string->string логика меняться не должна. Тем не менее, если убрать приведение, глюк исчезает. Баг в менеджере памяти, или неучтенные особенности поведения типов String или Variant?
Аноним (2007-03-11 16:17:00) [3]Не надо фаст ММ
и ShareMem не надо
Надо использовать типы, которые не вынуждают использовать внешние менеджеры
Belorus (2007-03-11 15:47:00) [4]FASTMM4 используй.
RWolf (2007-03-11 13:02:00) [5][b]MBo[/b], верно - про string помню, а про д.м. - забыл. Буду переделывать.
MBo (2007-03-11 12:41:00) [6]>array of PChar
динамический массив передаешь - а о ShareMem позаботился?
RWolf (2007-03-11 12:39:00) [7][b]clickmaker[/b], game - глобальная переменная, заполняется единожды при старте, объявлена так:
[code]type
TDefs=record
Code:string;
Title:string;
...
end;
var
game:TDefs;[/code]
clickmaker (2007-03-11 12:09:00) [8]а точно в этой строке?
в приведенной части кода все законно
на всякий случай, как game.Code инициализируется? и не может ли он стать невалидным к моменту s2:=code?