通过奇怪的修改阻止此访问冲突的原因是什么?

JO *_*Gng 0 delphi access-violation

我在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; 
Run Code Online (Sandbox Code Playgroud)

当我修改最后一行时,它可以正常工作.

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

Dav*_*nan 5

_IPAdapterAddresses := AllocMem(_SizePointer);
Run Code Online (Sandbox Code Playgroud)

此时_SizePointer是未初始化的变量.它的价值是不确定的.谁知道你分配了多少内存?当然你没有.由于该值是不确定的,因此代码中的任何更改都可能导致使用不同的值.

GetAdaptersAddresses(2, 128, nil, _IPAdapterAddresses, @_sizepointer);
Run Code Online (Sandbox Code Playgroud)

您无法检查此调用的返回值.所以你不知道它是否成功.如果呼叫失败,那么您没有理由期望_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.
Run Code Online (Sandbox Code Playgroud)

  • 你要求指针的大小,因为你有一个32位进程,那就是4.没有任何理由让你试图查询一个内存块的大小,这是你无论如何都做不到的.你刚刚分配了块,你知道它有多大.另外,请不要使用您问题中的代码.它不会检查错误. (3认同)