本地字符串数组初始化

时间:2013-12-27 00:11:22

标签: arrays delphi delphi-2006

我有偶发问题(单位系统中的访问冲突) 应用程序全天候运行,每周运行一次 - 两次 我有一个带有本地字符串数组的过程,我发现有些情况下我将非初始化数组成员分配给字符串变量,如下面的代码所示。
这可能是违反访问权限的原因吗?

procedure tform1.DoSomething;
var
   sarr: array [1..4] of String;
   s: String;
begin
   sarr[1] := 'aaaa';
   sarr[2] := 'bbbb';
   s := sarr[3]; // Can I get here an access violation???
end;

下面的实用功能代码 obj.opcode = cmdp_done时发生异常 从线程消息队列调用函数。 obj是在另一个线程中创建的,和 在PostThreadMessage中发送为msg.lparam

procedure ORTR_ProcessFiscalResponse(obj: TDataForOrpak);
    const
      maxdim = 4;
    var
      s: array [1..maxdim] of String;
      i, n, fiscalNr, statusToSend: Integer;
      sql, pdf, ortrName, docType, rut: String;
      ortr: TCustomizedOrtr;
      oFiscal: TFiscalDevice;
      fpds: TFPDeviceState;
    begin
      try
        case obj.opcode of
          cmdp_status:    N := 3;
          cmdp_done:      N := 2;
          plcl_docissued: N := 4;
          plcl_docfailed: N := 1;
          else
            Exit;
        end;
        for i:=1 to n do
          s[i] := GetTerm(obj.ident, i, ';');
        if s[1] = '' then
          Exit;
        statusToSend := 0;
        ortrName := GetTerm(s[1], 1, '+');
        fiscalNr := StrToIntDef(GetTerm(s[1]+'+', 2, '+'), 999999);
        docType := s[3];
        rut := s[4];
        ortr := TCustomizedOrtr.GetTerminalByName(ortrName) as TCustomizedOrtr;
        if ortr = nil then
          Exit;
        if (ortr.FPState = fps_idle) or (ortr.fiscalNr <> fiscalNr) then begin
          if (StrToIntDef(s[2], 0) <> 0) and (obj.opcode = cmdp_done) then
            fiscal_Confirm(obj.otherdevname, obj.ident);
          if obj.opcode = plcl_docissued then begin
            try
              PLCL_SetDocState(s[1], rut, false, StrToInt(s[2]), StrToInt(docType));
            except
              AddToLogFile('*** PLCL_SetDocState', log_exceptions);
            end;
          end;
          Exit;
        end;
        oFiscal := fiscal_Assigned(ortr.ctlPump.PumpID) as TFiscalDevice;
        case obj.opcode of
          plcl_docissued:
            begin
              ortr.authData.ECRReceiptNr := s[2];
              pdf := StringFromHexPresentation(obj.rawdata);
              sql := format(sql_PaperlessAdd, [
                ToLocalSQL_DateTime(ortr.ctlPump.FinalTime),
                ToLocalSQL_Integer(ortr.ctlPump.PumpID),
                ToLocalSQL_String(pdf)]);
              try
                UpdateLocalDB(sql);
              except
                AddToLogFile('*** PL save pdf', log_exceptions);
              end;
              try
                PLCL_SetDocState(s[1], rut, true, StrToInt(s[2]), StrToInt(docType));
              except
                AddToLogFile('*** PLCL_SetDocState', log_exceptions);
              end;
              ortr.FPState := fps_idle;
              ortr.currStage := TTextIndexType(0);
              ortr.currStage := tivirt_towelcome;  // VADIM
              ExternalProcessPumpState(ortr.authData.gsPump.PumpID);
            end;
          plcl_docfailed:
            ortr.FPState := fps_plerror;
          cmdp_status:
            begin
              ortr.FPError := StrToIntDef(s[3], 0);
              fpds := TFPDeviceState(StrToIntDef(s[2], 0));
              ortr.FPState := fpds;
              if (fpds in [fps_nocomm, fps_error]) and (ortr.fiscalMode = 1) and
                 (ortr.authData = nil) and (ortr.fiscalNr < 0) then
                    SpecialInterface.SendFiscalNrToPromax(-ortr.fiscalNr, '0');
              case fpds of
                fps_nopaper:  statusToSend := wph_prnpaperout;
                fps_nocomm:   statusToSend := wph_prncommfailure;
                fps_error:    statusToSend := wph_prngenericfailure;
              end;
            end;
          cmdp_done:
            begin
              if ortr.fiscalMode = 1 then begin
                if ortr.authData = nil then begin // DRY GOOD
                  SpecialInterface.SendFiscalNrToPromax(-fiscalNr, s[2]);
                end
                else begin
                  ortr.authData.ECRReceiptNr := s[2];
                  ExternalProcessPumpState(ortr.authData.gsPump.PumpID);
                end
              end;
              if StrToIntDef(s[2], 0) <> 0 then
                fiscal_Confirm(obj.otherdevname, obj.ident);
              statusToSend := wph_prnidle;
              ortr.FPState := fps_idle;
              ortr.currStage := ti_takereceipt;
            end;
        end;
        if (statusToSend <> 0) and (oFiscal <> nil) then
          PostNonVisualCommand(nv_devicestate, statusToSend, Integer(oFiscal));
      finally
        obj.free;
      end;
    end;

1 个答案:

答案 0 :(得分:0)

您的初始代码tform1.DoSomething例程无法产生访问冲突:

因此,您只需指定一个空字符串,s仍为空。


关于您的实际代码,假设它 产生访问冲突,我的猜测是:

  • obj参数仍然引用已经销毁的对象
  • obj.opcode读取无效的内存,但由于它与数值进行比较,会通过,
  • Exit子句中调用case else
  • obj.Free在finally子句中失败。

1 除字符串function results外,所有字符串变量都被初始化为空:

  

如果函数退出而没有为Result或函数名赋值,则函数的返回值是未定义的。

missing compiler warningstill a bug