最近写了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内部析构函数在回收内存的时候出现的问题。高分求解................................................

解决方案 »

  1.   

    看不出什么问题来,只是TStrings是抽象类,不能直接使用。
      

  2.   

    d对啊,你这么写不报错么
    是否应该这么写 myStringList:=TStringList.create;
      

  3.   

    是否应该这么写 myStringList:=TStringList.create;
      

  4.   

    就是这句的问题了:
    myStringList.create;
      

  5.   

    这个属于低级错误....
    纯属成蹭分var
      myStringList: TStrings;
    begin
      myStringList := TStringList.Create;
      try
        myStringList.LoadFormFile(filename);
      finally 
        myStringList.Free;
      end;
    end;
      

  6.   

    myStringList := TStringList.Create;
    呵呵,确实低级错误.
      

  7.   

    delphi里面报的可不是这个错啊,是堆栈溢出啊.另外,运行就该出错的.
      

  8.   

    myStringList.create;
    是否可以改成
    myStringList := TStringList.create;
      

  9.   

    sorry,那个错误是我的笔误
    因为代码太长乐,所以当时没有贴出来。
    呵呵,随手一写,就出了那么一个低级错误,
    实际的程序不是这样的。
    把所有代码贴出来吧
    -----------------------------------------------------------
    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;
      

  10.   

    这个函数我在一个简单的Demo里面执行的时候,竟然也没有问题,但是放到我的大程序里面就会出错了,我使用了多线程,会是这里的问题吗?
    可惜VCL不能打断点调试,否则可能能离错误更近一些。------------------------------------
    再次为我的那个笔误道歉,浪费大家的时间了。
      

  11.   

    VCL可以调试。选择 Project|Option->Complier->Use Debug DCUs ,即可调试VCL。出错的是哪行啊?
      

  12.   

    如果是多线程引起的话,那么最有可能的地方是
                       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
    总会进入循环的。
      

  13.   

    >>只是在关闭程序的时候才会出现错误
    噩梦级的问题
      

  14.   

    建议楼主调试一下---------------------------------------------
    第八个男人欢迎你
    http://www.debugman.com
      

  15.   

    for j := Pos('=', myStringList[i]) to Length(myStringList[i]) do肯定是这行引起的,不知道搂主这样写的用意是什么
      

  16.   

    myStringList:=TStringList.create;
      

  17.   

    这个mif格式之文档是否为纯文本格式?改成 TStream; 类来装载文件如何?
    对于多线程冒似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] 会出错呀。
      

  18.   

    for j := Pos('=', myStringList[i]) to Length(myStringList[i]) do肯定是这行引起的,不知道搂主这样写的用意是什么
    --------------------------------------------------------------------
    mif文件就是一个纯文本的文件,如果有搞过FPGA的朋友应该知道的。
    它是用来初始化内存单元的。
    我的这部分代码中间根本就没有什么容错机制,我知道是一段很烂的代码。
    只是我们用的mif文件都是用Quartus直接产生的,不会有什么格式上的错误,
    所以,我知道这一行肯定有'='在里面,所以我才这么写的。不知道你为什么觉得我的错误一定是这里产生的哪?ps:我选择了Use Debug DCUs之后,终于找到了错误的地方,就是system单元中的_FreeMem函数。我觉得应该是编译器自动释放一些内存单元的时候发生的错误,但是为什么会是我调用了这个函数之后才会出错,而我不掉用这个寒暑,就不会有问题哪?因为对_FreeMem的调用太多了,现在我都不知道是哪个地方调用了他,所以也跟踪不到出错的指针到底是哪一个。郁闷。
      

  19.   

    for i:=0 to length(wDatBuf) do
        begin
            wDatBuf[i] := 0;
        end;
    会不会越界?
    调用这个函数就出错,很有可能是这个函数中错误修改了一些指针的内容,导致delphi自动释放的时候,访问了错误的内存。
    建议楼主用一个比较短小的mif文件,在每次循环后,查看tempString的内容,看是否与预期的一致。
      

  20.   

    呵呵,我都不知道该哭还是该笑了...就是david981(菜鸟001) 说的原因。
    出这样的错误真是丢人啊,哈哈
    200分送上-------------------------------------
    希望大家往后不要犯我这样的毛病