用delphi好多年,第一次碰到奇怪的内存报错 望高手帮忙看下 谢谢

csm2432 2010-05-05 11:32:23
报错:
Access violation at address 006D9963 in module 'bath.exe'. Read of address 00000004.
调用 getBoxIdAndZone()函数前几次不会报错,后面再调用就会报上面的内存错,经过跟踪,错在下面一行(FCommIsWorking 是布尔型变量)
if not FCommIsWorking then
奇怪的是引用 变量 FCommIsWorking 怎么会报错吗?然后我在这句前面加了句
showmessage(booltostr(FCommIsWorking )) 再编译运行,报错后就定位在showmessage() 这句话,说明 是引用变量 FCommIsWorking 时有问题~~

代码如下(代码太长,完整代码见 http://bbs.2ccc.com/topic.asp?topicid=353134 ):

//RF卡管理类 提供查询、发牌、注销等功能
unit URFCardMng;

interface
uses
Classes, Controls, SysUtils, Forms, Variants,
Registry, Windows, Dialogs, StrUtils, UGlobalUnit;

Const
DLLPath='RF002Reader.dll';
Type
TPromptMsg = procedure(msg: string) of object;//提示信息 方法指针

TRFCardMng = class(TObject)
private
FCommIsWorking: Boolean; //串口是否已正常工作
FCommPort: integer;
FOnPromptMsg: TPromptMsg; //提示信息事件
reData:array of Variant;

FHandWareVer: string;//硬件版本
FProductDate: string;//出厂日期
FCustomID:Integer;
private
procedure sendPromptMsg(msg: string); //发送事件信息
function setCommPort(commPort: Integer): Integer;//设置串口端口 返回值 0: 成功 -1:失败; 1:串口已打开 ;2;串口端口不存在
procedure openComm();//如果串口没有打开则打开
public
constructor Create;
destructor Destory; overload;
public
{
自动打开串口

返回值:0:成功 其它值:失败
}
function autoOpenComm(): integer;


{
功能:读取手牌号与区域
boxId:取得的手牌号
zone:取得的区域名称
errMsg:错误信息
}
function getBoxIdAndZone(var boxId: string;var ZoneIndex: Integer; var errMsg: string): Integer;

procedure enterLock();
procedure leaveLock();

published
{
事件触发方法
if Assigned(OnPromptMsg) then
OnPromptMsg(Text);

}
property OnPromptMsg: TPromptMsg read FOnPromptMsg write FOnPromptMsg;

property HandWareVer: string read FHandWareVer; //硬件版本
property ProductDate: string read FProductDate; //出厂日期
// property CustomID: Integer read FCustomID ;
end;

implementation
var
FCriticalSection :TRTLCriticalSection;

function OpenReader(COMMNAME:integer):HWND; stdcall; external DLLPath name 'OpenReader';
function CloseReader():HWND; stdcall; external DLLPath name 'CloseReader';
function ReadRFID(Var RFIDData:Byte):DWORD; stdcall; external DLLPath name 'ReadRFID';
function SetCard(Var RFIDData:Byte):DWORD; stdcall; external DLLPath name 'SetCard';
function ClearCard(Var RFIDData:Byte):DWORD; stdcall; external DLLPath name 'ClearCard';
function GetReaderVersion(Var ReaderVersion:Byte):DWORD; stdcall; external DLLPath name 'GetReaderVersion';
function GetHandId(Var HandId:Byte):DWORD; stdcall; external DLLPath name 'GetHandId';
function SetHandId(Var HandId:Byte):DWORD; stdcall; external DLLPath name 'SetHandId';
function GetReaderRTC(var RTC:byte):DWORD; stdcall;external DllPath name 'GetRTC';
function SetReaderRTC(var RTC:byte):DWORD; stdcall;external DllPath name 'SetRTC';
function GetHandType(Var HandType:Byte):DWORD; stdcall; external DLLPath name 'GetHandType';
function SetHandType(Var HandType:Byte):DWORD; stdcall; external DLLPath name 'SetHandType';

{ TRFCardMng }

constructor TRFCardMng.Create;
begin
FCommIsWorking := False;
openComm;
end;

destructor TRFCardMng.Destory;
begin
end;

function TRFCardMng.setCommPort(commPort: Integer): Integer;
var
RetVal:DWORD;
tmpVersion:array [0..9] of byte;
begin
try
if FCommPort = commPort then
begin
Result := 0;
exit;
end;

FCommPort := commPort;
Result := 0;
FCommIsWorking := True;
RetVal:=OpenReader(CommPort); //执行DLL函数,打开读卡器,传入参数为读卡器对应的串口号码
if (RetVal=0) then
begin
FcommPort := 0;
FCommIsWorking :=False;
Result:=-1; //返回打开异常
exit;
end;
RetVal:=GetReaderVersion(tmpVersion[0]); //查询读卡器版本信息
if (RetVal=$00) then //读版本指令返回正常
Begin
FHandWareVer:=chr(tmpVersion[1])+chr(tmpVersion[2])+chr(tmpVersion[3])+chr(tmpVersion[4]);
FProductDate:=IntToHex(tmpVersion[5],2)+IntToHex(tmpVersion[6],2);;
FCustomID:= tmpVersion[7]*256+ tmpVersion[8];
if (FCustomID>$0000) then
begin
sendPromptMsg('[COM' + IntToStr(commPort) + ']'+'联机成功,硬件版本: '+FHandWareVer+' 出厂日期:'+FProductDate+' 客户代码: '+IntToHex(FCustomID,4));
end
else
begin
sendPromptMsg('联机成功,硬件版本: '+FHandWareVer+' 内部专用');
end
end
else
begin
sendPromptMsg('[COM' + IntToStr(commPort) + ']' + '通讯失败!');
FCommIsWorking := False;
Result := -1;
end;

except
on e:exception do
begin
if UpperCase(e.Message) = 'PORT ALREADY OPEN' then
begin
Result := 1;//串口已打开
sendPromptMsg('[COM' + IntToStr(commPort) + ']' + '串口已打开');
end
else if UpperCase(e.Message) = 'INVALID PORT NUMBER' then
begin
Result := 2;//串口端口不存在
sendPromptMsg('[COM' + IntToStr(commPort) + ']' + '串口端口不存在');
end
else
begin
sendPromptMsg('[COM' + IntToStr(commPort) + '] 错误:' + e.Message);
end;

end;
end;

end;


function TRFCardMng.getBoxIdAndZone(var boxId: string;var ZoneIndex: Integer; var errMsg: string): Integer;
var
RetVal:DWORD;
tmpHandId:array [0..5] of byte;
begin
// openComm;
try
enterLock();
if not FCommIsWorking then
begin
Result := 98;//串口未打开
errMsg := '串口未打开';
sendPromptMsg('串口未打开');
exit;
end;


Result := -1;
errMsg := '读卡时:未知错误';
RetVal:=GetHandId(tmpHandId[0]); //调用DLL读手牌码指令
if ((RetVal=0) and ((tmpHandId[0] xor tmpHandId[1] xor tmpHandId[2])=tmpHandId[3])) then
Begin
boxId := IntTohex(tmpHandId[0]*$100+tmpHandId[1],4);
ZoneIndex := tmpHandId[2]; //getZone( (RecData[3]-48) mod 4 ) ;
sendPromptMsg('读手牌与门禁通道码成功');
Result := 0;
end
else
begin
errMsg := '读手牌与区域异常';
sendPromptMsg('读手牌与门禁通道码异常');
Result := 2;
end;

finally
leaveLock();
end;

end;



procedure TRFCardMng.sendPromptMsg(msg: string);
begin
{
try
if Assigned(OnPromptMsg) then
begin
OnPromptMsg(msg);
end;
except

end;
}
end;


function TRFCardMng.autoOpenComm: integer;
var
reg:TRegistry;
ts:TStrings;
commPort: Integer;
i: integer;
begin
try
enterLock();
try
Result := -1;
reg := TRegistry.Create;
reg.RootKey := HKEY_LOCAL_MACHINE;
reg.OpenKey('hardware\devicemap\serialcomm',false);
ts:=TStringList.Create;
commPort := UGlobalUnit.ReadIniFile('RFCard','commport',0);
if commPort <> 0 then
begin
if setCommPort(commPort) = 0 then //设置串口成功
begin
Result := 0;
Exit;
end;
end;

reg.GetValueNames(ts);
if ts.Count = 0 then
begin
sendPromptMsg('未找到串行通讯端口');
end;
for i := 0 to ts.Count-1 do
begin
commPort := StrToInt( Copy(reg.ReadString(ts.Strings[i]),4,MaxInt) );
if setCommPort(commPort) = 0 then //设置串口成功
begin
UGlobalUnit.WriteIniFile('RFCard','commport',commPort);
Result := 0;
Break;
end;
end;
except
on e: Exception do
begin
sendPromptMsg('[COM' + IntToStr(commPort) + ']错误:' + e.Message);
end;
end;

finally
ts.Free;
reg.CloseKey;
reg.free;
leaveLock();
end;
end;

procedure TRFCardMng.openComm;
begin
try
enterLock();
if not FCommIsWorking then
begin
if autoOpenComm <> 0 then
begin
sendPromptMsg('打开串口失败');
end;
end;
finally
leaveLock();
end;

end;
function TRFCardMng.getCustomId: string;
begin
Result := IntToHex(FCustomID,4);
end;

procedure TRFCardMng.enterLock;
begin
EnterCriticalSection(FCriticalSection);
end;

procedure TRFCardMng.leaveLock;
begin
LeaveCriticalSection(FCriticalSection);
end;

initialization
InitializeCriticalSection(FCriticalSection); //初始化
finalization
DeleteCriticalSection(FCriticalSection); //删除
end.

...全文
270 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
iqyely 2010-05-07
  • 打赏
  • 举报
回复
学习下。
fangliang168 2010-05-07
  • 打赏
  • 举报
回复
学习一下!
yct0605 2010-05-07
  • 打赏
  • 举报
回复
恭喜楼主,接分了。
AsheBin 2010-05-07
  • 打赏
  • 举报
回复
恭喜楼主,接分!
huangheguyun 2010-05-07
  • 打赏
  • 举报
回复
ts.Free;
reg.CloseKey;
reg.free;
leaveLock();

被释放了!
hongss 2010-05-06
  • 打赏
  • 举报
回复
恭喜下
yktd26 2010-05-06
  • 打赏
  • 举报
回复
那接点分
csm2432 2010-05-06
  • 打赏
  • 举报
回复
问题已搞定,是对象被释放了

5,388

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧