关于Eaccessviolation错误的讨论. (200分)

  • 主题发起人 主题发起人 老赵
  • 开始时间 开始时间

老赵

Unregistered / Unconfirmed
GUEST, unregistred user!
程序编译运行没有问题.监视内存,很正常(不会直线增长)。
运行一段时间后(时间不定,可能10几分钟,也可能4、50分钟),会报错
Eaccessviolation错误。
由于里面动态getmem及freemem,还有Tmemorystream.create、free及指针操作内存。我怀疑是由于频繁建立
释放造成内存混乱。
现在的问题是:如何让程序发现此问题后,能够继续运行?
已经
try
try
....
except
exit;
end;
finally
...
end;
可还是有问题。
 
或者说,怎样真正才能保证程序的健壮?
 
出现Eaccessviolation错误是因为你的程序访问了无效的内存区域!建议你再完善你的程序。
你不妨换种异常处理方式比如,这样:
try
try
......
......
finally
end;
....
except
exit;
end;
在Try…Except 结构中嵌套try.....finally 结构,先释放资源,再进行异常处理,这样试试。

当应用程序出现异常时,如果应用程序没有专门处理异常,Application实例会自动调用HandleExcept方法,
HandleExcept方法首先查找应用程序有没有Application实例中的onExeption事件,若有就执行响应这个事件的代码,
如果没有,就自动调用Application实例中的ShowException方法,ShowException方法将推出一个提示窗口显示有关异常信息。
你其实可以做一个自己的异常处理程序。

unit
........
interface
..........
type
........
procedure MyErrorMessage(Sender:TObject;E: Exception);

implementation

procedure TForm1.MyErrorMessage(Sender: TObject; E: Exception);
begin
......
if e is Eaccessviolation then //判断异常类型
.....
end;
procedure Tform1.FormCreate(Sender: TObject);
begin
........
Application.OnException:=Form1.MyErrorMessage; //代替默认的异常处理句柄
............
end;


最后你再设置一些关于禁止堆栈检查的编译指示试试。。。。

也可以参考:
http://www.delphibbs.com/delphibbs/dispq.asp?lid=620575
 
访问了无效的内存区域!
 
你得把源码写出来啊,这样空谈没什么意义.`
 
非常同意sahee的说法,没什么说的,就是你自己的程序有问题,即:资源没建立或已经释放了,却要
访问。
 
我也出现这个问题,搞得我很头痛
 
用调试软件设置中断调试一下,内存问题还是好抓的^_^
 
//函數功能:讀Sybase第一二類
//傳入參數:無
//返回值:是否成功
bool __fastcall TFMain::GetSyBase()
{
Press->CGPress->AddProgress(1);
Application->ProcessMessages();
FileCount=0;//初始化
// GetCounter();
//
try{
//讀odxDocument表
RE->Lines->Add(DateTimeToStr(Now())+":讀Sybase第一二類...");
RE->Lines->Add(DateTimeToStr(Now())+":讀odxDocument表...");
adoqSyBase->Close();
String sql =" select * from odxDocument ";
sql=sql+" where systemCode="+DM(systemCode)+" and docTxnNo="+docTxnNo+" and dataSource="+DM(dataSource);
adoqSyBase->SQL->Text=sql;
adoqSyBase->Open();
[h1][red]在這邊會出現:Eaccessviolation[/red][/h1]
//為什么,大家能不能help me

RE->Lines->Add(DateTimeToStr(Now())+":讀odxDocument表..."+sql);
if(adoqSyBase->Eof)//找不到相應的記錄退出
{
RE->Lines->Add("找不到相應的記錄");
RE->Lines->SaveToFile(ExtractFilePath(Application->ExeName)+"//Process.ini");
ShowMessage("找不到相應的記錄");
return false;
}
isRegistered=false;
if( adoqSyBase->FieldByName("isRegistered")->AsString=="Y" )//判斷是否已經挂號
{
ShowMessage("該文已經掛號了");
isRegistered=true;
return false;
}
else
{
Added=ReadDBF(nocountdbf);//讀no_coount.dbf 并加一
if(Added==false)
return false; //讀失敗返回
}
String tmpPATH=FILEPATH.Trim();//用于存放Sybase的下載的附件的路徑
RE->Lines->Add(DateTimeToStr(Now())+":讀Sybase第一二類...");
Press->CGPress->AddProgress(2);
Application->ProcessMessages();

//讀數據
systemCode=adoqSyBase->FieldByName("systemCode")->AsString;
docTxnNo=adoqSyBase->FieldByName("docTxnNo")->AsString;
dataSource=adoqSyBase->FieldByName("dataSource")->AsString;
senderOrgId=adoqSyBase->FieldByName("senderOrgId")->AsString;
classId=adoqSyBase->FieldByName("classId")->AsString;
securityId=adoqSyBase->FieldByName("securityId")->AsString;
speedId=adoqSyBase->FieldByName("speedId")->AsString;
docDate=adoqSyBase->FieldByName("docDate")->AsString;
dtTemp=adoqSyBase->FieldByName("docDate")->AsDateTime;
docYear=adoqSyBase->FieldByName("docYear")->AsString;
docWord=adoqSyBase->FieldByName("docWord")->AsString;
docId=adoqSyBase->FieldByName("docId")->AsString;
typeId=adoqSyBase->FieldByName("typeId")->AsString;
docSubject=adoqSyBase->FieldByName("docSubject")->AsString;
fileDesc=adoqSyBase->FieldByName("fileDesc")->AsString;
RE->Lines->Add(DateTimeToStr(Now())+":讀odxDocument表 Ok!");
Press->CGPress->AddProgress(5);
Application->ProcessMessages();
RE->Lines->Add(DateTimeToStr(Now())+"讀 ID Doc");
TypeFile=adoqSyBase->FieldByName("fileDesc")->AsString.Trim();
TrueFileName[FileCount]=TypeFile;
RE->Lines->Add(DateTimeToStr(Now())+"讀 ID Doc:"+TypeFile);
TBlobField *FieldPtr;
FieldPtr=(TBlobField*)adoqSyBase->FieldByName("Contents");

int i=0;
RE->Lines->Add(DateTimeToStr(Now())+":查找Temp下的文件");
//生成要壓縮的文件名
while(FileExists(ExtractFilePath(Application->ExeName) + "temp"+"//"+AnsiString(i)+".z")||FileExists(ExtractFilePath(Application->ExeName) + "temp"+"//"+AnsiString(i)))
{
Press->CGPress->AddProgress(5);
FMain->Cursor=crHourGlass;
i++;
}
RE->Lines->Add(DateTimeToStr(Now())+":查完Temp下的文件");

TempFileName[FileCount]=AnsiString(i);//壓縮的文件名放入數組
FMain->Cursor=crDrag;
String tmpFile=ExtractFilePath(Application->ExeName) + "temp"+"//"+AnsiString(i)+".z";
RE->Lines->Add(DateTimeToStr(Now())+":Create di :"+tmpFile);
FieldPtr->SaveToFile(tmpFile);
RE->Lines->Add(DateTimeToStr(Now())+":解壓臨時Di:"+tmpFile);
DeCompress(tmpFile);//解壓文件
RE->Lines->Add(DateTimeToStr(Now())+"讀 ID Doc:"+TypeFile+"ok!");
FileCount++;
Press->CGPress->AddProgress(5);
Application->ProcessMessages();
//*********************************************************************
//處理PDF本文檔
//讀odxDocPdf表
RE->Lines->Add(DateTimeToStr(Now())+":讀odxDocPdf表...");
adoqSyBase->Close();
sql=" select * from odxDocPdf ";
sql=sql+" where systemCode="+DM(systemCode)+" and docTxnNo="+docTxnNo+" and dataSource="+DM(dataSource);
adoqSyBase->SQL->Text=sql;
adoqSyBase->Open();
[h1][red]在這邊會出現:Eaccessviolation[/red][/h1]
//為什么,大家能不能help me
Press->CGPress->AddProgress(5);
Application->ProcessMessages();
if(adoqSyBase->Eof) //找相應的odxDocPdf記錄
{
RE->Lines->Add("找不到相應的odxDocPdf記錄");
RE->Lines->SaveToFile(ExtractFilePath(Application->ExeName)+"//Process.ini");
}
else
{
fileDesc=adoqSyBase->FieldByName("fileDesc")->AsString;
RE->Lines->Add(DateTimeToStr(Now())+":讀odxDocPdf表 Ok!");
Press->CGPress->AddProgress(10);
Application->ProcessMessages();
RE->Lines->Add(DateTimeToStr(Now())+"讀 Pdf Doc");
PDFFile=adoqSyBase->FieldByName("fileDesc")->AsString.Trim();
if(PDFFile.Pos(".di")>0)
PDFFile=PDFFile.SubString(1,PDFFile.Length()-2)+"PDF";
if(PDFFile.Pos(".DI")>0)
PDFFile=PDFFile.SubString(1,PDFFile.Length()-2)+"PDF";
TrueFileName[FileCount]=PDFFile;
RE->Lines->Add(DateTimeToStr(Now())+"讀 Pdf Doc:"+PDFFile);
//存PDF 檔
TBlobField *FieldPtr;
FieldPtr=(TBlobField*)adoqSyBase->FieldByName("Contents");
int i=0;
RE->Lines->Add(DateTimeToStr(Now())+":查找Temp下的文件");
//成生臨時文件名
while(FileExists(ExtractFilePath(Application->ExeName) + "temp"+"//"+AnsiString(i)+".z")||FileExists(ExtractFilePath(Application->ExeName) + "temp"+"//"+AnsiString(i)))
{
Press->CGPress->AddProgress(5);
FMain->Cursor=crHourGlass;
i++;
}
RE->Lines->Add(DateTimeToStr(Now())+":查完Temp下的文件");
TempFileName[FileCount]=AnsiString(i);//存臨時文件名
FMain->Cursor=crDrag;
String tmpFile=ExtractFilePath(Application->ExeName) + "temp"+"//"+AnsiString(i)+".z";
RE->Lines->Add(DateTimeToStr(Now())+":Create PDF :"+tmpFile);
FieldPtr->SaveToFile(tmpFile);
RE->Lines->Add(DateTimeToStr(Now())+":解壓臨時PDF:"+tmpFile);
DeCompress(tmpFile);//解壓
RE->Lines->Add(DateTimeToStr(Now())+"讀 PDF Doc:"+PDFFile+"ok!");
FileCount++;
Press->CGPress->AddProgress(5);
Application->ProcessMessages();
}

//處理PDF本文檔
//*********************************************************************
//讀附件表(odxAttach)
RE->Lines->Add(DateTimeToStr(Now())+"讀附件表");
fileDesc="";
sql="select * from odxAttach";
sql=sql+" where systemCode="+DM(systemCode)+" and docTxnNo="+docTxnNo+" and dataSource="+DM(dataSource);
adoqSyBase->Close();
adoqSyBase->SQL->Text=sql;
adoqSyBase->Open();
attachCount=adoqSyBase->RecordCount;
strSERIAL="";//用于存放附件序號
RE->Lines->Add(DateTimeToStr(Now())+":生成附件的循環開始");
while(!adoqSyBase->Eof)
{

SERIAL=adoqSyBase->FieldByName("attachSeq")->AsString;
//fileDesc=adoqSyBase->FieldByName("fileDesc")->AsString.Trim();
if(fileDesc!="")
fileDesc=fileDesc+","+adoqSyBase->FieldByName("fileDesc")->AsString.Trim();
else
fileDesc=adoqSyBase->FieldByName("fileDesc")->AsString.Trim();
if(strSERIAL!="")
strSERIAL=strSERIAL+","+adoqSyBase->FieldByName("attachSeq")->AsString;
else
strSERIAL=adoqSyBase->FieldByName("attachSeq")->AsString;

TBlobField *FieldPtr;
FieldPtr=(TBlobField*)adoqSyBase->FieldByName("Contents");
TrueFileName[FileCount]=adoqSyBase->FieldByName("fileDesc")->AsString.Trim();
int i=0;
//生成臨時文件名
RE->Lines->Add(DateTimeToStr(Now())+":查找Temp下的文件以取得臨時附件的文件名");
while(FileExists(ExtractFilePath(Application->ExeName) + "temp"+"//"+AnsiString(i)+".z")||FileExists(ExtractFilePath(Application->ExeName) + "temp"+"//"+AnsiString(i)))
{
FMain->Cursor=crHourGlass;
i++;
}
RE->Lines->Add(DateTimeToStr(Now())+":查找完Temp下的文件以取得臨時附件的文件名");
TempFileName[FileCount]=AnsiString(i);////存臨時文件名
String tmpFile=ExtractFilePath(Application->ExeName) + "temp"+"//"+AnsiString(i)+".z";
FieldPtr->SaveToFile(tmpFile);//保存
RE->Lines->Add(DateTimeToStr(Now())+":生成附臨時文件:"+tmpFile);
DeCompress(tmpFile);//解壓
RE->Lines->Add(DateTimeToStr(Now())+":解壓臨時文件:"+tmpFile);
FileCount++;//附件數加一
Press->CGPress->AddProgress(1);
Application->ProcessMessages();
adoqSyBase->Next();
}
RE->Lines->Add(DateTimeToStr(Now())+":生成附件的循環結束");
RE->Lines->Add(DateTimeToStr(Now())+":完成附件");
Press->CGPress->AddProgress(10);
Application->ProcessMessages();
//查出相應的機關全銜
sql=" select * From TORG where (ORG_NO+ORG_DEPTNO)='"+senderOrgId.Trim()+"'";
adoqSyBase->Close();
adoqSyBase->SQL->Text=sql;
adoqSyBase->Open();
if(!adoqSyBase->Eof)
{
senderOrgId=adoqSyBase->FieldByName("ORG_NAME")->AsString;
}
adoqSyBase->Close();



}
catch(Exception &e)
{
RE->Lines->Add("讀Sybase失敗:"+e.Message);
RE->Lines->SaveToFile(ExtractFilePath(Application->ExeName)+"//Process.ini");
AddTxt("Error:"+e.Message);
ShowMessage("讀Sybase失敗:"+e.Message);


return false;
}
DeCompressAll();//解壓
RE->Lines->Add(DateTimeToStr(Now())+":讀完Sybase的數據");
return true;

}
//函數功能:讀Sybase第三類
//傳入參數:無
//返回值:是否成功
 
我认为可以借鉴C++中的处理方法,用一个对象(auto_ptr)来封装对动态申请内存的操作,
这样,我们可以通过控制对象的生存周期来控制内存的申请,释放。
type
TAutoPtr = class
private
FPtr :Pointer ;
FLen :Integer ;
public
property Ptr:Pointer read FPtr ;
property Len:Integer read FLen write setLen ;
constructor Create(bufflen :integer) ;
destructor Destroy ;
end ;
 
多人接受答案了。
 
后退
顶部