我正在使用Delphi XE3。我想了解更多关于如何正确使用然后释放指针的信息。我有两个指针lpParams和pHolder。我想知道我是否必须使用pHolder的类型指针以及在此例程中释放两个pinter的正确方法。谢谢。
function TmyLine.LineOpen(dwLineDevice: Integer;
var wMediaMode: Integer;
phLine,
plTAPIVersion: pLongInt): Integer;
var lOwnership,
lResult: LongInt;
lpParams: pTLineCallparams; // first pointer
pHolder: Pointer; // second pointer
dwAddressID, dwMediaMode: DWORD;
begin
if not bDeviceInitialized then
lResult := -1
else
begin
pHolder := nil; // default is nil unless we are using the singleaddress method
lOwnership := 0;
if FPrivilege.bSingleAddress then
begin
lOwnership := lOwnership + LINEOPENOPTION_SINGLEADDRESS;
try
lpParams := AllocMem(SizeOf(TLineCallParams) + 128); // make up a big enough value
except
lpParams := nil;
exit; // should I exit here? what about if there is an error? do I free pHolder?
end;
lpParams.dwTotalSize := sizeof(TLineCallParams) + 128;
lpParams.dwAddressMode := LINEADDRESSMODE_ADDRESSID;
pHolder := lpParams; // is this ok? Do i need a typed pointer?
end;
lResult := lineOpen(Fline.hLineApp, // fnd 64bit, see if longint needs to be dword_ptr
dwLineDevice,
phLine,
plTAPIVersion^,
FTAPI.lExtVersion,
DWORD_PTR(Self), //Pointer to the control, it is passed to the Callback routine as the lCallBackInstance parameter
lOwnership,
wMediaMode,
pHolder); // using the pointer here
if lResult <> 0 then
begin
pHolder := nil;
lpParams := nil; // is the the right way to do this?
end
else
begin
lineSetStatusMessages(temp);
end;
end;
pHolder := nil; // is this the correct way to free things up?
if lpParams <> nil then freemem(lpParams, sizeof(TLineCallParams) + 128);
LineOpen := lResult;
end;
答案 0 :(得分:2)
首先,您正在填写dwAddressMode
字段,但您没有填写dwAddressID
字段。您需要填写dwAddressID
,否则使用LINEOPENOPTION_SINGLEADDRESS
无效。
其次,lineOpen()
不会获取您传递给它的LINECALLPARAMS
指针的所有权。您必须在lineOpen()
退出后自行解除内存,无论其结果如何,例如:
function TmyLine.LineOpen(dwLineDevice: Integer;
var wMediaMode: Integer;
phLine,
plTAPIVersion: pLongInt): Integer;
var
lOwnership: DWORD;
lpParams: pTLineCallparams;
begin
Result := -1;
if not bDeviceInitialized then Exit;
lOwnership := 0;
lpParams := nil;
try
if FPrivilege.bSingleAddress then
begin
try
lpParams := AllocMem(SizeOf(TLineCallParams));
except
Exit;
end;
lpParams.dwTotalSize := sizeof(TLineCallParams);
lpParams.dwAddressID := ...; // don't forget to fill this in!
lpParams.dwAddressMode := LINEADDRESSMODE_ADDRESSID;
lOwnership := LINEOPENOPTION_SINGLEADDRESS;
end;
Result := lineOpen(Fline.hLineApp,
dwLineDevice,
phLine,
plTAPIVersion^,
FTAPI.lExtVersion,
DWORD_PTR(Self),
lOwnership,
wMediaMode,
lpParams);
finally
if lpParams <> nil then
FreeMem(lpParams, sizeof(TLineCallParams));
end;
if Result = 0 then
lineSetStatusMessages(...);
end;
第三,由于您只填写LINECALLPARAMS
的标准字段而不是任何扩展名,因此您根本不需要在堆上动态分配LINECALLPARAMS
。您可以选择静态地在堆栈上分配它(这就是为什么lineOpen()
无法获得它的所有权),例如:
function TmyLine.LineOpen(dwLineDevice: Integer;
var wMediaMode: Integer;
phLine,
plTAPIVersion: pLongInt): Integer;
var
lOwnership: DWORD;
Params: TLineCallparams;
lpParams: pTLineCallparams;
begin
Result := -1;
if not bDeviceInitialized then Exit;
lOwnership := 0;
lpParams := nil;
if FPrivilege.bSingleAddress then
begin
Params.dwTotalSize := sizeof(TLineCallParams);
Params.dwAddressID := ...; // don't forget to fill this in!
Params.dwAddressMode := LINEADDRESSMODE_ADDRESSID;
lpParams := @Params;
lOwnership := LINEOPENOPTION_SINGLEADDRESS;
end;
Result := lineOpen(Fline.hLineApp,
dwLineDevice,
phLine,
plTAPIVersion^,
FTAPI.lExtVersion,
DWORD_PTR(Self),
lOwnership,
wMediaMode,
lpParams);
if Result = 0 then
lineSetStatusMessages(...);
end;