GETIPFROMHOST memory leak

I have this code right here to extract the IP address from the host name:

program Project1; {$APPTYPE CONSOLE} uses SysUtils, winsock; function GetIPFromHost(const HostName: string): string; type TaPInAddr = array[0..10] of PInAddr; PaPInAddr = ^TaPInAddr; var phe: PHostEnt; pptr: PaPInAddr; i: Integer; begin Result := ''; phe := GetHostByName(PChar(HostName)); if phe = nil then Exit; pPtr := PaPInAddr(phe^.h_addr_list); i := 0; while pPtr^[i] <> nil do begin Result := inet_ntoa(pptr^[i]^); Inc(i); end; end; var wsaData: TWSAData; begin if (WSAStartup($0202, wsaData) <> 0) then begin Exit; end; while true do begin sleep (1000); GetIPFromHost ('localhost'); end; 

It works fine and gives me an IP address. Unfortunately, I need this function several times to compare DNS with IP address.

For some reason, I get a lot of memory leaks, and the memory of my program increases very quickly. Why is this and how can I free memory?

Thanks in advance.

+7
source share
3 answers

This code does not leak. Either the leak detection is faulty, or the code that you are actually executing is more complicated than this, and the leak is in the code that you did not show.

The only memory allocated by Delphi RTL in the code in the question is for dynamic strings. Delphi dynamic line processing does not proceed. WinSock, gethostbyname and inet_ntoa allocate internal memory for WinSock.

In the case of gethostbyname :

The hostent memory returned by gethostbyname is allocated inside the Winsock DLL from the local thread store. Only one host structure is allocated and used, regardless of how many times the gethostbyaddr or gethostbyname functions are called in the stream. The returned host structure must be copied to the application buffer if additional calls must be made in the gethostbyname or gethostbyaddr functions in the same thread. Otherwise, the return value will be overwritten by subsequent calls to gethostbyname or gethostbyaddr in the same stream. The internal memory allocated for the returned host structure is issued by the Winsock DLL when the stream exits.

And also for inet_ntoa :

The string returned by inet_ntoa is in memory allocated by Windows sockets. An application should not make any assumptions about how memory is allocated. The returned string is guaranteed to be valid only until the next call to the Windows Sockets function is made within the same thread.

Although it is true that the code in the question does not call WSACleanup , this is fine, since it is pretty pointless to return resources in the process at the end time.

+3
source

Here's how GetIPAddress implemented in JclSysInfo :

 function GetIPAddress(const HostName: string): string; var R: Integer; WSAData: TWSAData; HostEnt: PHostEnt; Host: string; SockAddr: TSockAddrIn; begin Result := ''; R := WSAStartup(MakeWord(1, 1), WSAData); if R = 0 then try Host := HostName; if Host = '' then begin SetLength(Host, MAX_PATH); GetHostName(PChar(Host), MAX_PATH); end; HostEnt := GetHostByName(PChar(Host)); if HostEnt <> nil then begin SockAddr.sin_addr.S_addr := Longint(PLongint(HostEnt^.h_addr_list^)^); Result := inet_ntoa(SockAddr.sin_addr); end; finally WSACleanup; end; end; 

Note that you are missing WSACleanup .


An application or DLL is required to successfully call WSAStartup before it can use Windows Sockets Services. When it finishes using Windows sockets, the application or DLL must call WSACleanup to unregister from the Windows Sockets implementation and allow the implementation to release any resources allocated on behalf of the application or DLL.

+4
source

This code works with Delphi XE2 and XE3

Add " Winsock " to Usage Section

 //function to get the IP Address from a Host function GetIPFromHost(HostName: string): string; type TaPInAddr = array[0..10] of PInAddr; PaPInAddr = ^TaPInAddr; var phe: PHostEnt; pptr: PaPInAddr; i: Integer; GInitData: TWSAData; begin WSAStartup($101, GInitData); try Result := ''; phe := GetHostByName(PAnsiChar(AnsiString((HostName)))); if phe = nil then Exit; pPtr := PaPInAddr(phe^.h_addr_list); i := 0; while pPtr^[i] <> nil do begin Result := string(inet_ntoa(pptr^[i]^)); Inc(i); end; finally WSACleanup; end; end;e 
+2
source

All Articles