为什么此代码在按钮内部工作,而不是在单个过程中?

时间:2012-03-03 03:50:11

标签: delphi winapi pointers stack-overflow access-violation

我正在将原生WiFi API的WinAPI翻译成delphi,我在一个按钮内写了一个rotine来测试,并且它有效。但是在程序中没有工作,我无法弄清楚为什么因为我只是复制和粘贴。

这个确切的代码是工作

procedure TForm1.Button1Click(Sender: TObject);
var
nVersion:DWORD;
clientHandle:HWND;
return:DWORD;
size:DWORD;
pdata:pWLAN_HOSTED_NETWORK_CONNECTION_SETTINGS;
vtype:pWLAN_OPCODE_VALUE_TYPE;
pfail:PWLAN_HOSTED_NETWORK_REASON;
ssid:array[0..DOT11_SSID_MAX_LENGTH] of UCHAR;
name:String;
begin
    return:=WlanOpenHandle(2,nil,@nVersion,@clientHandle);
    return:=WlanHostedNetworkQueryProperty(clientHandle,wlan_hosted_network_opcode_connection_settings,@size,@pdata,@vtype,nil);
    if return<>ERROR_SUCCESS then ShowMessage('Returned ERROR '+ IntToStr(return));

  name:=Edit1.Text;
    StrCopy(@pdata.hostedNetworkSSID.ucSSID, @name[1]);
    pdata.hostedNetworkSSID.uSSIDLength:=Length(name);

    return:=WlanOpenHandle(2,nil,@nVersion,@clientHandle);
    return:=WlanHostedNetworkSetProperty(clientHandle,wlan_hosted_network_opcode_connection_settings,size,pdata,@pfail,nil);
    if return<>ERROR_SUCCESS then ShowMessage('Returned ERROR '+ IntToStr(return));
end;

但如果将此代码放在另一个过程中以使代码清理并在按钮内调用该函数,则它不起作用!

procedure setSSID(text:String);
var
nVersion:DWORD;
clientHandle:HWND;
return:DWORD;
size:DWORD;
pdata:pWLAN_HOSTED_NETWORK_CONNECTION_SETTINGS;
vtype:pWLAN_OPCODE_VALUE_TYPE;
pfail:PWLAN_HOSTED_NETWORK_REASON;
ssid:array[0..DOT11_SSID_MAX_LENGTH] of UCHAR;
name:String;
begin
    return:=WlanOpenHandle(2,nil,@nVersion,@clientHandle);
    return:=WlanHostedNetworkQueryProperty(clientHandle,wlan_hosted_network_opcode_connection_settings,@size,@pdata,@vtype,nil);
    if return<>ERROR_SUCCESS then ShowMessage('Returned ERROR' + IntToStr(return)); <<<<<< RETURNING ERROR 1734

  name:=text;
    StrCopy(@pdata.hostedNetworkSSID.ucSSID, @name[1]);
    pdata.hostedNetworkSSID.uSSIDLength:=Length(name);

    return:=WlanOpenHandle(2,nil,@nVersion,@clientHandle);
    return:=WlanHostedNetworkSetProperty(clientHandle,wlan_hosted_network_opcode_connection_settings,size,pdata,@pfail,nil);
    if return<>ERROR_SUCCESS then ShowMessage('Returned ERROR '+ IntToStr(return));
end;


procedure TForm1.Button1Click(Sender: TObject);
begin
    setSSID('test');
end;

我在突出显示的行上收到错误1734,然后收到Access violation at address 004084D0 in module Project1.exe. Write of address 000000000.

我找不到任何问题,因为代码完全一样!

function WlanHostedNetworkQueryProperty(
  hClientHandle:HANDLE;
  OpCode:WLAN_HOSTED_NETWORK_OPCODE;
  pdwDataSize:PDWORD;
  ppvData:PPVOID;
  pWlanOpcodeValueType:PWLAN_OPCODE_VALUE_TYPE;
  pvReserved:PVOID
):DWORD; stdcall; external 'Wlanapi.dll';


function WlanHostedNetworkSetProperty(
  hClientHandle:HANDLE;
  OpCode:WLAN_HOSTED_NETWORK_OPCODE;
  dwDataSize:DWORD;
  pvData:PVOID;
  pFailReason:PWLAN_HOSTED_NETWORK_REASON;
  pvReserved:PVOID
):DWORD; stdcall; external 'Wlanapi.dll';

** OBS:如果我将行name:=text;更改为name:='hello';则可行!我仍然不知道为什么,可能是与指针和内存溢出相关的东西。**

2 个答案:

答案 0 :(得分:6)

WlanHostedNetworkQueryProperty函数的文档指出在调用时,pData指针必须设置为nil。你根本没有初始化它,所以可能是也可能不是,具体取决于堆栈的状态。您需要添加以下行:

pData:= nil;

电话前

您可能希望初始化所有参数。

(抱歉格式不正确,尝试在手机上执行此操作很难!)

答案 1 :(得分:-1)

我实际上是在另一个问题的帮助下解决了这个问题。

访问冲突是由delphi的正常行为引起的。

  

Delphi字符串的内存管理有点不寻常。在你之后   调用myFunc(text),并指定textcopy:= mytext,这三个变量   (text,mytext和textcopy)将指向同一个地址   原始字符串。

     

但是只要您使用其中一个变量对其进行更改   字符串,Delphi克隆幕后的字符串,以及您的更改   适用于副本。另外两个变量仍然指向   原来,所以他们保持不变。因此,在Context 2中进行的任何更改   将不会在上下文1中看到 - 这种“写时复制”机制   有效地为您提供按值传递的语义。所有这些字符串   是引用计数,并将自动释放   参考文献超出了范围。

     

但是,有一个例外如果您使用访问字符串   指针,而不是字符串操作,你将绕过复制   步骤和您的更改将影响原始。你也可以绕过   引用计数逻辑,可能以指向a的指针结束   解除分配的内存块。这可能是您访问背后的原因   违规,但我不能说没有更多细节/更多代码。

     

如果您想要引用传递,请将您的函数声明为myFunc(var   mytext:String)。如果你想强制Delphi复制字符串,   而不是等到它被修改,你可以使用   System.UniqueString。

原始答案https://stackoverflow.com/a/9543812/938822