最近写了Component,专门用于读写.mif文件的,开始的时候条是没有什么问题,但是加到大程序里面用的时候,在关闭程序的时候总是会跳出异常提示:Invalid pointer operation,其实应用很简单,就是用TStringList将mif文件的每行读近来,然后对每行进行处理。
大体的应用是这样的
var
myStringList: TStrings;
begin
myStringList.create;
myStringList.LoadFormFile(filename);
//deal with the mif file
myStringList.Free;
end;不知道是什么问题了,出错的时候也没有提示错误在那一行
我估计是VCL内部析构函数在回收内存的时候出现的问题。高分求解................................................
大体的应用是这样的
var
myStringList: TStrings;
begin
myStringList.create;
myStringList.LoadFormFile(filename);
//deal with the mif file
myStringList.Free;
end;不知道是什么问题了,出错的时候也没有提示错误在那一行
我估计是VCL内部析构函数在回收内存的时候出现的问题。高分求解................................................
解决方案 »
- SampleGrabber1.GetBitmap(Image1.Picture.Bitmap)在64位系统中抓取不到图像
- 一个sql2000两个实例的问题
- 文本操作
- 请邹建等高手看看:如何在存储过程中执行跨网段的事务
- 使用SetTimer后';' expected but 'IMPLEMENTATION' found 的错误
- 新手的字体设置问题,请求大哥们帮忙!
- 把INTRAWEB的程序INSTALL到SERVICES里,但是这样一台机器只能开一个INTRAWEB程序,只这样吗???
- 请问一对socket之间可以既用来传送数组又来传送文本吗
- 推荐好书
- 求教:多层开发的一个小概念?
- 触发器的困惑!!
- wm
是否应该这么写 myStringList:=TStringList.create;
myStringList.create;
纯属成蹭分var
myStringList: TStrings;
begin
myStringList := TStringList.Create;
try
myStringList.LoadFormFile(filename);
finally
myStringList.Free;
end;
end;
呵呵,确实低级错误.
是否可以改成
myStringList := TStringList.create;
因为代码太长乐,所以当时没有贴出来。
呵呵,随手一写,就出了那么一个低级错误,
实际的程序不是这样的。
把所有代码贴出来吧
-----------------------------------------------------------
procedure TMifFile.LoadFromMifFile(fileName: String);
var
i, j, tempInt: integer;
iDepth: integer;
iCurrentCounter: integer;
iStartIndex, iEndIndex: integer;
iTempValue: integer;
rAddressRadix, rDataRadix: TRadix;
bStartGetContext: Boolean;
myStringList: TStrings;
tempString: string;
const
CONST_WIDTH = 'WIDTH';
CONST_DEPTH = 'DEPTH';
CONST_ADDRESS_RADIX = 'ADDRESS_RADIX';
CONST_DATA_RADIX = 'DATA_RADIX';
CONST_BEGIN = 'CONTENT BEGIN';
CONST_END = 'END'; CONST_BIN = 'BIN';
CONST_OCT = 'OCT';
CONST_UNS = 'UNS';
CONST_HEX = 'HEX';
begin
{----------------------初始化变量----------------------------------------------}
iDepth := 0; //数据深度
rAddressRadix := ERR; //地址格式
rDataRadix := ERR; //数据格式
iCurrentCounter := -1; //数据项计数
bStartGetContext := False;
for i:=0 to length(wDatBuf) do
begin
wDatBuf[i] := 0;
end;
{---------------------读取mif文件----------------------------------------------}
myStringList := TStringList.Create;
myStringList.LoadFromFile(fileName);
{---------------------处理mif文件----------------------------------------------}
for i:=0 to myStringList.Count-1 do
begin
//对非注释行进行处理
if Pos('--', myStringList[i]) = 0 then
begin
//获取mif文件数据宽度
if Pos(CONST_WIDTH, myStringList[i]) <> 0 then
begin
tempString := '';
for j := Pos('=', myStringList[i]) to Length(myStringList[i]) do
begin
if TryStrToInt(myStringList[i][j], tempInt) then
tempString := tempString + myStringList[i][j];
end;
// iWidth := StrToInt(tempString);
end;
//获取mif文件数据深度
if Pos(CONST_DEPTH, myStringList[i]) <> 0 then
begin
tempString := '';
for j := Pos('=', myStringList[i]) to Length(myStringList[i]) do
begin
if TryStrToInt(myStringList[i][j], tempInt) then
tempString := tempString + myStringList[i][j];
end;
iDepth := StrToInt(tempString);
end;
//获取mif文件地址格式
if Pos(CONST_ADDRESS_RADIX, myStringList[i]) <> 0 then
begin
if Pos(CONST_BIN, myStringList[i]) <> 0 then
rAddressRadix := BIN
else if Pos(CONST_OCT, myStringList[i]) <> 0 then
rAddressRadix := OCT
else if Pos(CONST_UNS, myStringList[i]) <> 0 then
rAddressRadix := UNS
else if Pos(CONST_HEX, myStringList[i]) <> 0 then
rAddressRadix := HEX;
end;
//获取mif文件数据格式
if Pos(CONST_DATA_RADIX, myStringList[i]) <> 0 then
begin
if Pos(CONST_BIN, myStringList[i]) <> 0 then
rDataRadix := BIN
else if Pos(CONST_OCT, myStringList[i]) <> 0 then
rDataRadix := OCT
else if Pos(CONST_UNS, myStringList[i]) <> 0 then
rDataRadix := UNS
else if Pos(CONST_HEX, myStringList[i]) <> 0 then
rDataRadix := HEX;
end;
//获取mif文件数据内容开始标志
if Pos(CONST_BEGIN, myStringList[i]) <> 0 then
begin
bStartGetContext := True;
end;
if Pos(CONST_END, myStringList[i]) <> 0 then
begin
bStartGetContext := False;
if (iCurrentCounter + 1) = iDepth then
begin
if Assigned(FOnReadFinish) then
FOnReadFinish(wDatBuf, iDepth);
end;
end;
//开始获取数据内容
if bStartGetContext then
begin
if Pos(':', myStringList[i]) <> 0 then
begin
if Pos('[', myStringList[i]) <> 0 then
begin
//计算开始位置
tempString := '';
for j := Pos('[', myStringList[i]) to Pos('..', myStringList[i]) do
begin
if TryStrToInt('$' + myStringList[i][j], tempInt) then
tempString := tempString + myStringList[i][j];
end;
iStartIndex := myStrToInt(tempString, rAddressRadix);
//计算结束位置
tempString := '';
for j := Pos('..', myStringList[i]) to Pos(']', myStringList[i]) do
begin
if TryStrToInt('$' + myStringList[i][j], tempInt) then
tempString := tempString + myStringList[i][j];
end;
iEndIndex := myStrToInt(tempString, rAddressRadix);
iCurrentCounter := iEndIndex;
//计算填写数据
tempString := '';
for j := Pos(':', myStringList[i]) to Length(myStringList[i]) do
begin
if TryStrToInt('$' + myStringList[i][j], tempInt) then
tempString := tempString + myStringList[i][j];
end;
iTempValue := myStrToInt(tempString, rDataRadix);
//完成数据填写
for j := iStartIndex to iEndIndex do
wDatBuf[j] := iTempValue;
end
else//对于单位置单数据的情况进行处理
begin
//计算数据地址
tempString := '';
for j := 0 to Pos(':', myStringList[i]) do
begin
if TryStrToInt('$' + myStringList[i][j], tempInt) then
tempString := tempString + myStringList[i][j];
end;
iTempValue := myStrToInt(tempString, rAddressRadix);
//计算数据内容
tempString := '';
for j := Pos(':', myStringList[i]) to Length(myStringList[i]) do
begin
if TryStrToInt('$' + myStringList[i][j], tempInt) then
tempString := tempString + myStringList[i][j];
end;
//给正确位置赋值
wDatBuf[iTempValue] := myStrToInt(tempString, rDataRadix);
iCurrentCounter := iTempValue;
end;
end;
end;
end;
end;
myStringList.Free;
end;
可惜VCL不能打断点调试,否则可能能离错误更近一些。------------------------------------
再次为我的那个笔误道歉,浪费大家的时间了。
if Assigned(FOnReadFinish) then
FOnReadFinish(wDatBuf, iDepth);
但是程序中有几个地方还是不明白,像
for j := Pos('=', myStringList[i]) to Length(myStringList[i]) do
当找不到‘=’时,j=0,这样也会进入循环,这个时候可能访问myStringList[i][0],而字符串的第0个字节一般保存长度的,不是实际的有效字符。还有诸如
for j := 0 to Pos(':', myStringList[i]) do
总会进入循环的。
噩梦级的问题
第八个男人欢迎你
http://www.debugman.com
对于多线程冒似Delphi有个TThreadXXXXList之类东东
"可惜VCL不能打断点调试,否则可能能离错误更近一些。" --- VCL可以调吧,你没源码?
如下代码可能是不安全的吧?
for j := 0 to Pos(':', myStringList[i]) do
begin
if TryStrToInt('$' + myStringList[i][j], tempInt) then
tempString := tempString + myStringList[i][j];
end;
iTempValue := myStrToInt(tempString, rAddressRadix);如果Pos返回0 哪么 myStringList[i][0] 会出错呀。
--------------------------------------------------------------------
mif文件就是一个纯文本的文件,如果有搞过FPGA的朋友应该知道的。
它是用来初始化内存单元的。
我的这部分代码中间根本就没有什么容错机制,我知道是一段很烂的代码。
只是我们用的mif文件都是用Quartus直接产生的,不会有什么格式上的错误,
所以,我知道这一行肯定有'='在里面,所以我才这么写的。不知道你为什么觉得我的错误一定是这里产生的哪?ps:我选择了Use Debug DCUs之后,终于找到了错误的地方,就是system单元中的_FreeMem函数。我觉得应该是编译器自动释放一些内存单元的时候发生的错误,但是为什么会是我调用了这个函数之后才会出错,而我不掉用这个寒暑,就不会有问题哪?因为对_FreeMem的调用太多了,现在我都不知道是哪个地方调用了他,所以也跟踪不到出错的指针到底是哪一个。郁闷。
begin
wDatBuf[i] := 0;
end;
会不会越界?
调用这个函数就出错,很有可能是这个函数中错误修改了一些指针的内容,导致delphi自动释放的时候,访问了错误的内存。
建议楼主用一个比较短小的mif文件,在每次循环后,查看tempString的内容,看是否与预期的一致。
出这样的错误真是丢人啊,哈哈
200分送上-------------------------------------
希望大家往后不要犯我这样的毛病