2016-02-25 73 views
0

我在Windows 10中使用西雅圖。奇怪的修改阻止了這種訪問衝突的原因是什麼?

我嘗試打印公共IP地址和網關地址。

訪問衝突發生在最後一行。

當我刪除第1行時,它運行良好。

uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, System.Win.ComObj, Vcl.StdCtrls, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdHTTP, winapi.iphlpapi, winapi.iptypes, winapi.winsock; 

type 
    TForm1 = class(TForm) 
    Label1: TLabel; 
    Label2: TLabel; 
    IdHTTP1: TIdHTTP; 
    procedure FormCreate(Sender: TObject); 
    end; 

procedure TForm1.FormCreate(Sender: TObject); 
var 
    _IPAdapterAddresses: PIP_ADAPTER_ADDRESSES; 
    _SizePointer: Integer; 
begin 
    Label2.Caption := Label2.Caption + ' ' + IdHTTP1.Get'http://ipinfo.io/ip'); // line 1 

    _IPAdapterAddresses := AllocMem(_SizePointer); 

    GetAdaptersAddresses(2, 128, nil, _IPAdapterAddresses, @_sizepointer); 

    Label1.Caption := Label1.Caption + ' ' + string(inet_ntoa(_IPAdapterAddresses^.FirstGatewayAddress.Address.lpSockaddr.sin_addr)); // access violation 
end; 

當我修改最後一行,如下所示,它運作良好。

Label1.Caption := {Label1.Caption + ' ' + }string(inet_ntoa(_IPAdapterAddresses^.FirstGatewayAddress.Address.lpSockaddr.sin_addr)); 
end; 

回答

5
_IPAdapterAddresses := AllocMem(_SizePointer); 

此時_SizePointer是未初始化的變量。它的價值是不確定的。誰知道你分配了多少內存?當然你不知道。由於該值是不確定的,因此代碼中的任何更改都可能導致使用不同的值。

GetAdaptersAddresses(2, 128, nil, _IPAdapterAddresses, @_sizepointer); 

您無法檢查此調用的返回值。所以你不知道它是否成功。如果通話失敗,那麼你沒有理由期待_IPAdapterAddresses包含任何使用。無論如何,你可能沒有爲_IPAdapterAddresses分配足夠的內存。

最重要的是,您已經分配了堆內存,但未能釋放它,從而導致它泄漏。

您正在尋找這些方針的東西:

{$APPTYPE CONSOLE} 

uses 
    System.SysUtils, 
    Winapi.IpHlpApi, 
    Winapi.IpTypes, 
    Winapi.WinSock, 
    Winapi.Windows; 

const 
    GAA_FLAG_INCLUDE_GATEWAYS = $0080; 

procedure Main; 
var 
    Addresses: PIP_ADAPTER_ADDRESSES; 
    OutBufLen: ULONG; 
    Retval: ULONG; 
begin 
    OutBufLen := 15*1024; // MSDN recommendation is to use a 15kB buffer 
    GetMem(Addresses, OutBufLen); 
    try 
    Retval := GetAdaptersAddresses(AF_INET, GAA_FLAG_INCLUDE_GATEWAYS, nil, Addresses, 
     @OutBufLen); 
    if Retval = ERROR_BUFFER_OVERFLOW then 
    begin 
     ReallocMem(Addresses, OutBufLen); 
     Retval := GetAdaptersAddresses(AF_INET, GAA_FLAG_INCLUDE_GATEWAYS, nil, Addresses, 
     @OutBufLen); 
    end; 
    if Retval <> ERROR_SUCCESS then 
     RaiseLastOSError(Retval, ''); 
    Writeln(inet_ntoa(Addresses^.FirstGatewayAddress.Address.lpSockaddr.sin_addr)); 
    finally 
    FreeMem(Addresses); 
    end; 
end; 

begin 
    try 
    Main; 
    except 
    on E: Exception do 
     Writeln(E.ClassName, ': ', E.Message); 
    end; 
    Readln; 
end. 
+0

我根據一個類似的例子設置大小15000在這裏,它工作良好。我試圖使用sizeof,但輸出爲4.即使在我看到msdn的示例(sizeof(PIP_ADAPTER_ADDRESSES))後,我無法使用delphi獲取PIP_ADAPTER_ADDRESSES的大小。並釋放了記憶。感謝大衛。 –

+3

你在問一個指針的大小,而且你有一個32位的進程,那就是4.沒有任何理由要你去查詢內存塊的大小,反正你也做不到。你只是分配了塊,你知道它有多大。另外,請不要在你的問題中使用代碼。它不檢查錯誤。 –

相關問題