子线程中申请内存,主线程中释放会有问题吗? ( 积分: 50 )

  • 主题发起人 主题发起人 hegyi
  • 开始时间 开始时间
H

hegyi

Unregistered / Unconfirmed
GUEST, unregistred user!
问题是这样的,我在子线程中申请了一个指针变量pCB,然后,将pCB的地址作为参数PostMessage给主线程,在主线程中处理完后,dispose()这个内存,会有什么问题?
我在使用时,发现送到主线程的每一个pCB内容都正确,但有些不让访问内存……

代码大致如下:
//类型定义
TcomBlock=record
UserID:integer;
end
pComBlock=^TcomBlock;

//在子线程中生成打针变量
var
pCB:pComblock;
.....
new(pCB)
pCB.UserID=1234;
postMessage(MainForm.handle,MessageType,integer(pCB),0);

//在主线程中(上述的MainForm)
procedure TMainForm.HandleMsg(var Message:TMessage);
var
pCB:pComBlock
UserID:Integer;
begin
pCB:=pComBlock(Message.WParam);//到这里,pCB的内容完全正确
UserID:=pCB^.UserID ;这里有时出错
....
//处理完事务后消除内存
dispose(pCB);
end;
//上述整个过程都不出错,但发送多个pCB时,有些可能出错
 
看起来没有问题啊,NEW创建的内存是属于进程地址空间的,和线程无关,是不是有别处代码的问题
 
进程地址空间的,也就是说,在程序的任务地方清除New分配的内存都是可以的了?
 
new和dispose需要互斥,否则有可能导致堆出问题
 
to hegyi:
是的,只要保证一一对应就好了,我按照你的说法做了个测试程序,没有发现和你一样的问题

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

const
WM_TEST = WM_USER + 1;

type
TcomBlock=record
UserID:integer;
end;
pComBlock=^TcomBlock;

TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
protected
procedure NewMethod(var Message: TMessage)
message WM_TEST;
procedure WndProc(var Message: TMessage)
override;
public
{ Public declarations }
end;

TTest = class(TThread)

protected
procedure Execute
override;
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
TTest.Create(false);
end;

procedure TForm1.NewMethod(var Message: TMessage);
var
pCB: pComBlock;
begin
pCB := pComBlock(Message.WParam);
Caption := IntToStr(pCB^.UserID);
Dispose(pCB);

inherited;
end;

procedure TForm1.WndProc(var Message: TMessage);
begin
inherited;

end;

procedure TTest.Execute;
var
pCB: pComBlock;
begin
while not Terminated do
begin
New(pCB);
pCB^.UserID := GetTickCount;
PostMessage(Form1.Handle, WM_TEST, Integer(pCB), 0);
Sleep(100);
end;

end;

end.


to mzlsx:
我不同意你的观点,这个互斥是由VCL的内存管理模块做的
getmem.inc

function SysGetMem(size: Integer): Pointer;
// Allocate memory block.
var
f, prev, next: PFree;
u: PUsed;
begin
...
try
if IsMultiThread then EnterCriticalSection(heapLock);
...
finally
if IsMultiThread then LeaveCriticalSection(heapLock);
end;
 
谢谢回答问题

问题确实出在另一个地方:是我想当然地认为Record类型都是连续存储的。
 
后退
顶部