奇怪的修改阻止了这种访问冲突的原因是什么?

问题描述:

我在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; 

_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.没有任何理由要你去查询内存块的大小,反正你也做不到。你只是分配了块,你知道它有多大。另外,请不要在你的问题中使用代码。它不检查错误。 –