我写了一个线程类TPing = class(TThread)  用于 做ping操作procedure TPing.Execute;
begin
  ValidCheck();
  PingResult:=ping(IP,300);
  FreeWinsock();
  FreeOnTerminate:=true;
end;下面是 关于ping的相关代码:(取于网上)type
  PIPOptionInformation = ^TIPOptionInformation;
  TIPOptionInformation =record
    TTL: Byte;             //时间
    TOS: Byte;
    Flags: Byte;
    OptionsSize: Byte;     //字节
    OptionsData: PChar;   //返回数据
  end;  PIcmpEchoReply = ^TIcmpEchoReply;
  TIcmpEchoReply =record
    Address: DWORD;
    Status: DWORD;
    RTT: DWORD;     //返回时间
    DataSize:Word;  //字节数
    Reserved: Word;
    Data: Pointer;
    Options: TIPOptionInformation;  //上面声明的类型
  end;function IcmpCreateFile():THandle;stdcall external 'ICMP.dll';
function IcmpCloseHandle(Handle:THandle):Boolean;stdcall external 'ICMP.dll';
function IcmpSendEcho(Handle:THandle;DestAddr:DWORD;
         RequestData: Pointer;RequestSize: Word;RequestOptions: PIPOptionInformation;
         ReplyBuffer: Pointer;ReplySize: DWORD;Timeout: DWORD): DWORD;stdcall external 'ICMP.dll';
function TPing.Ping(IPAddr:String;TimeOut:Word):String;  //PING函数主体
var IPOpt:TIPOptionInformation;// IP Options for packet to send
    FIPAddress:DWORD;
    pReqData,pRevData:PChar;
    pIPE:PIcmpEchoReply;// ICMP Echo reply buffer
    FSize: DWORD;
    MyString:string;
    FTimeOut:DWORD;
    BufferSize:DWORD;
    temp:Integer;
    pIPAddr:Pchar;
begin
  //get ip
  GetMem(pIPAddr,Length(IPAddr)+1);  //建立一动态(指定大小的变量)并将指针移动到这
  ZeroMemory(pIPAddr,Length(IPAddr)+1);
  StrPCopy(pIPAddr,IPAddr);
  //calc
  FIPAddress := inet_addr(pIPAddr);  //IP转换成无点整型
  //free it
  FreeMem(pIPAddr);    //释放动态(指定大小)内存
  //valid check
  if FIPAddress=INADDR_NONE then   //INADDR_NONE=-1
  begin
    result:='0';
    exit;
  end;
  //package size
  FSize := 40;
  BufferSize := SizeOf(TICMPEchoReply) + FSize;
  GetMem(pRevData,FSize);  //声明2个动态内存
  GetMem(pIPE,BufferSize);
  //prepare data
  FillChar(pIPE^, SizeOf(pIPE^), 0);  //用指定的值填充连续字节的数
  pIPE^.Data := pRevData;
  MyString := 'Ping Digital Data';
  pReqData := PChar(MyString);
  FillChar(IPOpt, Sizeof(IPOpt), 0);   //把IPOpt用0填充后传给SIZEOF()
  //max delieve geteway
  IPOpt.TTL := 64;
  //time out
  FTimeOut := TimeOut;
  //statr   ping
  temp:=IcmpSendEcho(hICMP,               //dll handle
                     FIPAddress,          //target
                     pReqData,            //data
                     Length(MyString),    //data length
                     @IPOpt,              //addree of ping option
                     pIPE,//
                     BufferSize,          //pack size
                     FTimeOut);           //timeout value
  //check result
  if temp=0 then
  begin
     //没有响应
    result:='0';
    exit;
  end;
  if pReqData^ = pIPE^.Options.OptionsData^ then    //RESULT IS TRUE
  begin
    result:='1';
  end;
  //clear memory
  FreeMem(pRevData);//释放内存
  FreeMem(pIPE);
end;procedure TPing.ValidCheck();  //initiates DLL
var
   WSAData:TWSAData;
begin
  //initiates use of WS2_32.DLL
  if (WSAStartup(MAKEWORD(2,0),WSAData)<>0) then
    raise Exception.Create(SInitFailed);
  hIcmp:=IcmpCreateFile();   //返回DLL句柄
  if hICMP=INVALID_HANDLE_VALUE then
    raise Exception.Create('ICMP运行有误!!!   ');
end;procedure TPing.FreeWinsock();
begin
  IcmpCloseHandle(hIcmp);
  WSACleanUP;
end;
1、我每次创建线程,运行结束后,任务管理器 中内存使用都会有少许增加。
2、我在txt中写有1000个ip。将其读入TStringList后,用for循环对应创建1000个线程。此时线程运行结束后 内存增加的数目就比较多了。原本想法 1000个线程运行完后,由于'FreeOnTerminate:=true;' ,每个线程都应该释放资源的。但是为何占用内存增加了?理想状态:
用1000个线程对应1000个ip,用timer循环(比如10秒间隔),每次创建1000个线程,循环循环..... 从而判断这1000台机是否在线。但是1小时后,占用内存达百兆。why??

解决方案 »

  1.   

    怀疑是内存泄露了,用MemProof检查下
      

  2.   

    上面 ping 的代码,我另建了一个project,这次放在主线程中执行,直接用一个 button 调用(Ping('192.168.2.1',300);)
    差不多按下 button 十次之内,'内存使用'就会增加 几K。
      

  3.   

    MemProof 的Resources Details窗口如上图,但是我所有 GetMem之后都有FreeMem啊,VirtualAlloc不知为哪里用到的。求教 如何修改代码???
      

  4.   

    function TPing.Ping(IPAddr:String;TimeOut:Word):String;  //PING函数主体
    var IPOpt:TIPOptionInformation;// IP Options for packet to send
        FIPAddress:DWORD;
        pReqData,pRevData:PChar;
        pIPE:PIcmpEchoReply;// ICMP Echo reply buffer
        FSize: DWORD;
        MyString:string;
        FTimeOut:DWORD;
        BufferSize:DWORD;
        temp:Integer;
        pIPAddr:Pchar;
    begin
      //get ip
      GetMem(pIPAddr,Length(IPAddr)+1);  //建立一动态(指定大小的变量)并将指针移动到这
      ZeroMemory(pIPAddr,Length(IPAddr)+1);
      StrPCopy(pIPAddr,IPAddr);
      //calc
      FIPAddress := inet_addr(pIPAddr);  //IP转换成无点整型
      //free it
      FreeMem(pIPAddr);    //释放动态(指定大小)内存
      //valid check
      if FIPAddress=INADDR_NONE then   //INADDR_NONE=-1
      begin
        result:='0';
        exit;
      end;
      //package size
      FSize := 40;
      BufferSize := SizeOf(TICMPEchoReply) + FSize;
      GetMem(pRevData,FSize);  //声明2个动态内存     //申請了內存
      GetMem(pIPE,BufferSize);    ////申請了內存
      //prepare data
      FillChar(pIPE^, SizeOf(pIPE^), 0);  //用指定的值填充连续字节的数
      pIPE^.Data := pRevData;
      MyString := 'Ping Digital Data';
      pReqData := PChar(MyString);
      FillChar(IPOpt, Sizeof(IPOpt), 0);   //把IPOpt用0填充后传给SIZEOF()
      //max delieve geteway
      IPOpt.TTL := 64;
      //time out
      FTimeOut := TimeOut;
      //statr   ping
      temp:=IcmpSendEcho(hICMP,               //dll handle
                         FIPAddress,          //target
                         pReqData,            //data
                         Length(MyString),    //data length
                         @IPOpt,              //addree of ping option
                         pIPE,//
                         BufferSize,          //pack size
                         FTimeOut);           //timeout value
      //check result
      if temp=0 then
      begin
         //没有响应
        result:='0';
        exit;                 //  如果沒有響應;  直接返回,那麼:  FreeMem(pRevData);//释放内存    FreeMem(pIPE);    這個申請的內存就沒辦法釋放了。
      end;
      if pReqData^ = pIPE^.Options.OptionsData^ then    //RESULT IS TRUE
      begin
        result:='1';
      end;
      //clear memory
      FreeMem(pRevData);//释放内存
      FreeMem(pIPE);
    end;