平台:Windows 7 + Delphi 7
现象:主程序创建N个线程(>50),每个线程都会调用同一个DLL,线程内部为循环运行(除非Teiminate),大约1,2小时后开始报错。
主程序相关代码(仅示例代码,主程序及DLL均第一个单元引用FASTMM):TCreateOrder = function(DeviceID:PChar): PChar; stdcall;
procedure 
var  Func: TCreateOrder;
  t_dll:Cardinal;
begin  @Func := GetProcAddress(t_dll, 'CreateOrder');       //t_dll为exe建立时Load,,尝试过每次Load,问题依旧
  cmdSend    :=  Func(PChar(tcomid));                  
  //这里即为出错位置。Access violation at address 0C708563 in module 'ys.dll'. Write of address 00000000 In TThreadCJ
end; 
DLL代码:function CreateOrder(DeviceID:PChar): PChar;stdcall;
var
  order:array[0..6] of integer;
  i:integer;
  orderstring:string;
  CommID:integer;
begin
  try
    CommID := strtoint(DeviceID);
    order[0]:= CommID mod 200;
    order[1]:= commid div 200;
    order[2]:= 3;
    order[3]:= 0;
    order[4]:= 0;
    order[5]:= 0;
    order[6]:= 0;
    orderstring := '';
    for i:= 0 to 6 do
    begin
      orderstring := orderstring + inttohex(order[i],2) + ' ';
    end;
    Result := PChar(orderstring);
  except on e:exception do
    begin
        //
    end;
  end;
end;exports
    CreateOrder;

解决方案 »

  1.   

    取到的dll中CreateOrder函数地址为0,调用地址0就报AC错误了,1,2小时才出错,得看你线程的创建代码和线程执行的代码。 另外你可以把CreateOrder写在dll外再做下测试。
      

  2.   

    把CreateOrder写在dll外直接线程调用做测试,记得写日志记录上下文信息,然后去睡觉吧,明天看日志
      

  3.   

    修改为下面代码试下,我觉得问题出在dll函数中强制将String的变量转为PCHar作为返回值上(Result := PChar(orderstring);)function CreateOrder(DeviceID:PChar): PChar;stdcall;
    var
      order:array[0..6] of integer;
      i:integer;
      orderstring:PChar;//orderstring:string;
      CommID:integer;
    begin
      try
        CommID := strtoint(DeviceID);
        order[0]:= CommID mod 200;
        order[1]:= commid div 200;
        order[2]:= 3;
        order[3]:= 0;
        order[4]:= 0;
        order[5]:= 0;
        order[6]:= 0;
        {orderstring := '';
        for i:= 0 to 6 do
        begin
          orderstring := orderstring + inttohex(order[i],2) + ' ';
        end;
        Result := PChar(orderstring);}
        GetMem(orderstring, 7*2+1);
        try
          for i:= 0 to 6 do
            StrCopy(orderstring, PChar(inttohex(order[i], 2)));
          Result := orderstring;
        finally
          FreeMem(orderstring);
        end;
      except on e:exception do
        begin
            //
        end;
      end;
    end;
      

  4.   

    function CreateOrder(DeviceID:PChar): PChar;stdcall;
    var
      order:array[0..6] of integer;
      i:integer;
      orderstring:PChar;//orderstring:string;
      CommID:integer;
    begin
      try
        CommID := strtoint(DeviceID);
        order[0]:= CommID mod 200;
        order[1]:= commid div 200;
        order[2]:= 3;
        order[3]:= 0;
        order[4]:= 0;
        order[5]:= 0;
        order[6]:= 0;
        {orderstring := '';
        for i:= 0 to 6 do
        begin
          orderstring := orderstring + inttohex(order[i],2) + ' ';
        end;
        Result := PChar(orderstring);}
        GetMem(orderstring, 7*2+1);
        try
          for i:= 0 to 6 do
            StrCopy(orderstring, PChar(inttohex(order[i], 2)));
          Result := orderstring;
        finally
          FreeMem(orderstring);
        end;

      except on e:exception do
        begin
            //
        end;
      end;
    end;
      

  5.   

     首先很明显是个错误! Result := PChar(orderstring);觉得在调用分方配内存给被用方使用才是好办法! 另一个就是完全又被调用方管理内存,也就是分配和释放都有DLL来完成;
      

  6.   

    忘记还要将StrCopy(orderstring, PChar(inttohex(order[i], 2)));改为SysUtils.StrCat(orderstring, PChar(inttohex(order[i], 2)));
      

  7.   

    忘了说了。将DLL中函数CreateOrder直接写到EXE主程序中不会出错。已经连续运行3天,开了几台机器做测试,现在测试中,几乎每一步都做了LOG输出。
      

  8.   

    感谢feiba7288..连续运行几天,还没出现过错误,继续观察中。。应该是这个强制转换的问题。
      

  9.   

    orderstring离开函数已经被销毁,你还返回PChar(orderstring)。这个是个隐患。
      

  10.   

    觉得还要直接返回PCHAR,而是由调用者分配,传递进去,只返回结果的长度就好。
      

  11.   

    orderstring离开函数已经被销毁,你还返回PChar(orderstring)。这个是个隐患。 楼主一直不重视这个! 呵呵。