我正在尝试在Delphi函数中使用和释放2个指针。我如何正确地释放它们?
我正在使用delphixe3。我试图学习更多关于如何正确使用并释放指针的知识。我有两个指针lpParams和pHolder。我想知道我是否必须使用pHolder的类型指针,以及在这个例程中释放两个pinter的正确方法。多谢各位我正在尝试在Delphi函数中使用和释放2个指针。我如何正确地释放它们?,delphi,pointers,delphi-xe3,Delphi,Pointers,Delphi Xe3,我正在使用delphixe3。我试图学习更多关于如何正确使用并释放指针的知识。我有两个指针lpParams和pHolder。我想知道我是否必须使用pHolder的类型指针,以及在这个例程中释放两个pinter的正确方法。多谢各位 function TmyLine.LineOpen(dwLineDevice: Integer; var wMediaMode: Integer;
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;
函数TmyLine.LineOpen(dwLineDevice:Integer;
var wMediaMode:整数;
phLine,
pltAversion:pLongInt):整数;
var lOwnership,
结果:长;
lpParams:pTLineCallparams;//第一个指针
pHolder:指针;//第二个指针
dwAddressID,dwMediaMode:DWORD;
开始
如果未初始化,则
lResult:=-1
其他的
开始
pHolder:=nil;//除非使用singleaddress方法,否则默认值为nil
低能量:=0;
如果FPrivilege.bSingleAddress,则
开始
lOwnership:=lOwnership+LINEOPENOPTION\u SINGLEADDRESS;
尝试
lpParams:=AllocMem(SizeOf(TLineCallParams)+128);//组成一个足够大的值
除了
lpParams:=nil;
退出;//我应该在这里下车吗?如果有错误怎么办?我有空吗?
结束;
lpParams.dwTotalSize:=sizeof(TLineCallParams)+128;
lpParams.dwAddressMode:=LINEADDRESSMODE_ADDRESSID;
pHolder:=lpParams;//这样行吗?我需要键入的指针吗?
结束;
lResult:=lineOpen(Fline.hLineApp,//fnd 64位,查看longint是否需要为dword\u ptr
dwLineDevice,
phLine,
公共交通^,
FTAPI.lExtVersion,
DWORD_PTR(Self),//指向控件的指针,它作为lCallBackInstance参数传递给回调例程
低能,
wMediaMode,
pHolder);//在这里使用指针
如果lResult为0,则
开始
pHolder:=零;
lpParams:=nil;//这样做正确吗?
结束
其他的
开始
lineSetStatusMessages(临时);
结束;
结束;
pHolder:=nil;//这是解放一切的正确方法吗?
如果lpParams为nil,则为freemem(lpParams,sizeof(TLineCallParams)+128);
LineOpen:=lResult;
结束;
首先,您填写的是dwAddressMode
字段,但不是dwAddressID
字段。您需要填写dwAddressID
,否则使用LINEOPENOPTION\u 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;
这里有很多问题。很难知道该关注什么。尤其是我们对您调用的API一无所知。@DavidHeffernan对AllocMem的每次调用都应该有对FreeMem的相应调用,否则,它就是一个leak@EProgrammerNotFound是的。“但是问题中的其余代码都充满了问题。”大卫·费弗南在这种情况下,我认为我们应该只局限于回答OP的问题。在我看来,问题很清楚。@David:
lineOpen
是一个来自Win32(Tapi32.dll)的电话API(TAPI)函数。第一个版本可以返回,而无需设置Result
。FWIW,我认为你应该劝阻询问者以这种方式处理内存不足错误。异常不应被捕获在这里。@Remy,我想添加代码,我是否编辑我的原始帖子?我看不出如何继续一个线程并说,好吧,忽略前面的代码,这个怎么样……。@F.Decker:如果新代码与原始问题相关,您可以编辑原始问题。Remy和@DavidHeffernan,我对第一篇文章进行了编辑并更改了代码。谢谢大家!@大卫·费弗南,我迷路了。当我在这里看我的文章时,上面我为最终审查编辑的代码不在那里。但在它下面我看到了“大卫·赫弗南编辑”。当我点击它时,它会把我带到另一个页面,在那里我请求帮助的代码会显示出来。我必须已经发布了不止一次,因为我没有看到它出现,其中两个帖子是红线,最终版本在那里。版主必须批准它吗?
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;