代码如下://这段代码在ontest中可以正常接收到发过来的信息
procedure TForm1.btn1Click(Sender: TObject);
var pdata :array[0..4] of Byte ;
i : Integer;
begin
FillChar(pdata,5,0);
for i := 0 to 4 do
begin
pdata[i] := i * 10;
end;
PostMessage(Handle,WM_TEST,5,LongWord(@pdata[0]));
end;procedure TForm1.OnTest(var Msg: TMessage);
var pd : array[0..4] of Byte;
i : Integer;
begin
CopyMemory(@pd[0],Pointer(Msg.LParam),5);
for i := 0 to Msg.WParam - 1 do
begin
ShowMessage(IntToStr(pd[i]));
end;
end;//下面代码也可以正常接收,只是showmessage后会报错,不知什么原因
procedure TForm1.btn1Click(Sender: TObject);
var pdata :pByte ;
i : Integer;
begin
GetMem(pdata,5);
FillChar(pdata^,5,0);
for i := 0 to 4 do
begin
pdata^ := i * 10;
inc(LongWord(pdata),1);
end;
inc(LongWord(pdata),-5);
SendMessage(Handle,WM_TEST,5,LongWord(@pdata));
FreeMem(pdata,5);
end;procedure TForm1.OnTest(var Msg: TMessage);
var pd : pByte;
i : Integer;
aa : TBitmap;
begin
CopyMemory(@pd,Pointer(Msg.LParam),5);//拷贝正常,执行完毕报错
//Move(Pointer(Msg.LParam)^,(@pd)^,5);//正常
for i := 0 to Msg.WParam - 1 do
begin
ShowMessage(IntToStr(pd^));
if i < Msg.WParam - 1then
Inc(LongWord(pd),1);
end;
end;
哪位达人解释一下
另外 能不能通过 InterlockedExchange 这个PAI直接为pd指向一个地址?
procedure TForm1.btn1Click(Sender: TObject);
var pdata :array[0..4] of Byte ;
i : Integer;
begin
FillChar(pdata,5,0);
for i := 0 to 4 do
begin
pdata[i] := i * 10;
end;
PostMessage(Handle,WM_TEST,5,LongWord(@pdata[0]));
end;procedure TForm1.OnTest(var Msg: TMessage);
var pd : array[0..4] of Byte;
i : Integer;
begin
CopyMemory(@pd[0],Pointer(Msg.LParam),5);
for i := 0 to Msg.WParam - 1 do
begin
ShowMessage(IntToStr(pd[i]));
end;
end;//下面代码也可以正常接收,只是showmessage后会报错,不知什么原因
procedure TForm1.btn1Click(Sender: TObject);
var pdata :pByte ;
i : Integer;
begin
GetMem(pdata,5);
FillChar(pdata^,5,0);
for i := 0 to 4 do
begin
pdata^ := i * 10;
inc(LongWord(pdata),1);
end;
inc(LongWord(pdata),-5);
SendMessage(Handle,WM_TEST,5,LongWord(@pdata));
FreeMem(pdata,5);
end;procedure TForm1.OnTest(var Msg: TMessage);
var pd : pByte;
i : Integer;
aa : TBitmap;
begin
CopyMemory(@pd,Pointer(Msg.LParam),5);//拷贝正常,执行完毕报错
//Move(Pointer(Msg.LParam)^,(@pd)^,5);//正常
for i := 0 to Msg.WParam - 1 do
begin
ShowMessage(IntToStr(pd^));
if i < Msg.WParam - 1then
Inc(LongWord(pd),1);
end;
end;
哪位达人解释一下
另外 能不能通过 InterlockedExchange 这个PAI直接为pd指向一个地址?
procedure TForm1.OnTest(var Msg: TMessage);
var pd : array[0..4] of Byte ;
这样定义时,又该怎么拷贝?
不管PD有没有分配内存,执行完后都一样报错!既然是未分配内存报错,为何move又可以呢?
SendMessage(Handle,WM_TEST,5,LongWord(pdata));
以前发送结构体时,会加上@,发送一个地址,但现在发送的是指针,本身就是地址。
另外也可以这样
InterlockedExchange(Integer(pdata),Integer(Pointer(msg.LParam)));
在同一程序里,不为pdata分配内存,直接把pdata指向Pointer(msg.LParam)的地址。
发送方式是以sendmessage以送的。
i : Integer;
aa : TBitmap;
begin
CopyMemory(@pd,Pointer(Msg.LParam),5);//拷贝正常,执行完毕报错
楼主怎么想的呢?
32位系统下
pd : pByte pd只占4个字节,你要复制5个直接过去,溢出了,程序运行完出错,你应该感到很幸运了,如果偶尔出哈错,就不好找到这个地方了
直接
pd := Ptr(Msg.LParam);
即可,也不需要分配内存,
procedure ...
var
pdata :array[0..4] of Byte;
begin
...
PostMessage(Handle,WM_TEST,5,LongWord(@pdata[0]));
end;这种使用PostMessage是肯定不行的,数据一次没出错是运气好,并不代表一直都对
虽然确实可以实现交换,不过有点浪费总线资源了.
作了少少修改, 没有报错procedure TForm1.Button1Click(Sender: TObject);
var
pdata :pByte ;
i : Integer;
begin
GetMem(pdata,5);
FillChar(pdata^,5,0);
for i := 0 to 4 do
begin
pdata^ := i * 10;
inc(LongWord(pdata),1);
end;
inc(LongWord(pdata),-5);
SendMessage(Handle,WM_TEST,5,LongWord(@pdata));
FreeMem(pdata,5);
end;procedure TForm1.OnTest(var Msg: TMessage);
var pd : pByte;
i : Integer;
begin
CopyMemory(@pd,Pointer(LongWord(Msg.LParam)),Sizeof(Pointer(LongWord(Msg.LParam))));
for i := 0 to Msg.WParam - 1 do
begin
ShowMessage(IntToStr(pd^));
if i < Msg.WParam - 1then
Inc(LongWord(pd),1);
end;
end;
解释在这里
pd : pByte pd只占4个字节,你要复制5个直接过去,溢出了
procedure TfrmMain.OnTest(var msg: TMessage);
var i , size: Integer;
pdata : PByte;
hmem : Cardinal;
path : PChar;
begin
Size := msg.WParam;
// hmem := GlobalAlloc(GHND,5);
// pdata := GlobalLock(hmem);
InterlockedExchange(Integer(pdata),Integer(Pointer(msg.LParam)));
//发送方发送指针地址,不需分配内存
// Move(Pointer(msg.LParam)^,pdata^,5); //发送方发送指针地址 ,需分配内存
// CopyMemory(pdata,PByte(msg.LParam),5); //发送方发送指针地址 ,需分配内存
// pdata := ptr(msg.LParam); //发送方发送指针地址 ,不需分配内存
// CopyMemory(@pdata,Pointer(Msg.LParam),4); //发送方发送指针变量地址
// Move(Pointer(Msg.LParam)^,(@pdata)^,4); //发送方发送指针变量地址
for i := 0 to size - 1 do
begin
ShowMessage(IntToStr(pdata^ ));
Inc(LongWord(pdata),SizeOf(byte));
end;
// GlobalUnlock(hmem);
// GlobalFree(hmem);
end;procedure TfrmMain.btn1Click(Sender: TObject);
var pdata : pByte;
i : Integer;
begin
GetMem(pdata,5);
for i := 0 to 4 do
begin
pdata^ := i * 10;
Inc(LongWord(pdata),1);
end;
Inc(LongWord(pdata),-5);
SendMessage(Handle,WM_test,5,LongWord(pdata));
FreeMem(pdata,5);
end;
像 Inc(LongWord(pdata),1) 应该直接写 Inc(pdata);Inc(LongWord(pdata),-5) 应该写 Dec(pdata, 5);OnTest 里和多线程操作无关,InterlockedExchange 纯属多余,直接 pdata:=PByte(msg.LParam) 或者 pdata:=Pointer(msg.LParam) 就可以另外,如果要动态分配 pdata 内存的话,将 pdata 声明成 array of Byte 然后 SetLength 的话可以不用写释放的代码(我的 delphi 代码几乎不用 GetMem/FreeMem),按偏移量访问会更加轻松,也不用担心内存泄露。如果非要用 GetMem/FreeMem 的话,写在 try...finally 块里代码会更健壮一些。
同样,OnTest 里将 pdata 声明成 PByteArray 的话,按照偏移量访问会更容易一些。
CSDN居然没提示
我一开始发送消息是这么写的
SendMessage(Handle,WM_TEST,5,LongWord(@pdata));
//还在纠结哦
procedure TForm1.btn1Click(Sender: TObject);
var
//这里是私有变量,是栈上分配的,所以必须用SendMessage
pdata :array [0..4] of Byte;
i : Integer;
begin
// FillChar(pdata,5,0); 这句完全多余
for i := 0 to 4 do pdata[i] := i * 10;
SendMessage(Handle,WM_TEST,5,LongWord(@pdata)); //这样即可,这里是把pdata的指针传过去
end; //函数执行完后,就会释放栈上的数据,因此必须用SendMessage,SendMessage要等消息处理后才返回的,保证了传递过去的指针的数据有效procedure TForm1.OnTest(var Msg: TMessage);
var
pd : PByte;
i : Integer;
begin
pd := Pointer(Msg.LParam); //直接取传过来的指针即可,何必用CopyMemory?
for i := 0 to Msg.WParam - 1 do begin
ShowMessage(IntToStr(pd[i]));
inc(integer(pd));
end;
end;
ShowMessage(IntToStr(pd^));
inc(integer(pd));
不好意思,Sorry
SendMessage(Handle,WM_TEST,5,LongWord(pdata));
//1.CopyMemory(pd,Pointer(msg.LParam),msg.WParam);需要分配内存
//2.pd := Pointer(Msg.LParam); //直接使用,不需分配内存
//3.InterlockedExchange(Integer(pd),Integer(Pointer(msg.LParam)));//不需分配内存SendMessage(Handle,WM_TEST,5,LongWord(@pdata));
//1.CopyMemory(@pd,Pointer(LongWord(Msg.LParam)),Sizeof(Pointer(LongWord(Msg.LParam))));//不需分配内存
//2.Move(Pointer(Msg.LParam)^,(@pd)^,Sizeof(Pointer(LongWord(Msg.LParam))));
//不需分配内存
最主要的就是这两者的区别吧。怎么老觉得越整越糊涂了下面代码是想通过接收方来改变指针指向的内容procedure TForm1.onmessage(var msg: TMessage);
var pd : pByte;
i : Integer;
begin
pd := Ptr(Msg.LParam);
for i := 0 to Msg.WParam - 1 do
begin
ShowMessage(IntToStr(pd^));
pd^ := pd^ + 100;
inc(LongWord(pd));
end;
end;procedure TForm1.btn1Click(Sender: TObject);
var pdata :pByte ;
i : Integer;
begin
GetMem(pdata,5);
FillChar(pdata^,5,0);
for i := 0 to 4 do
begin
pdata^ := i * 10;
inc(LongWord(pdata));
end;
Dec(LongWord(pdata),5);
SendMessage(Handle,WM_TEST,5,LongWord(pdata));
for i := 0 to 4 do
begin
ShowMessage(IntToStr(pdata^));
inc(LongWord(pdata));
end;
// 这里值已经改变,但运行完后报错!不加这个循环就没问题,这是什么原因呢?
FreeMem(pdata,5);
end;
begin
pdata^ := i * 10;
inc(LongWord(pdata));
end;
Dec(LongWord(pdata),5); //这里知道减5
...
for i := 0 to 4 do
begin
ShowMessage(IntToStr(pdata^));
inc(LongWord(pdata));
end;
//这里为什么不减5 ???????????????申请内存时,假设你申请到的内存地址是$10000000
//通过上面的循环,你的pdata的值是$10000005,你调用FreeMem对$10000005进行释放,其结果可想而知
FreeMem(pdata,5);
都说了操作对像, 一个PBYTE, 你怎么可能申请内存为5啊????都说了, 一个PBYTE只是一个指针, 不是一个指针数组!!!!
Dec(LongWord(pdata),5); // FreeMem前加这一句
FreeMem(pdata,5);
FreeMem(pdata,5);
//你在31楼没有用COPYMEMORY了, 所以不聊COPYMEMORY的对像问题.
//31楼的代码, 加下面红色的语句, 跳回原来的地址, 就不会报错了.procedure TForm1.btn1Click(Sender: TObject);
var pdata :pByte ;
i : Integer;
begin
GetMem(pdata,5);
FillChar(pdata^,5,0);
for i := 0 to 4 do
begin
pdata^ := i * 10;
inc(LongWord(pdata));
end;
Dec(LongWord(pdata),5);
SendMessage(Handle,WM_TEST,5,LongWord(pdata));
for i := 0 to 4 do
begin
ShowMessage(IntToStr(pdata^));
inc(LongWord(pdata));
end;
Dec(LongWord(pdata),5); // FreeMem前加这一句
FreeMem(pdata,5);
end;
procedure TForm1.btn1Click(Sender: TObject);
var pdata :array[0..4] of Byte ;
i : Integer;
begin
FillChar(pdata,5,0);
for i := 0 to 4 do
begin
pdata[i] := i * 10;
end;
PostMessage(Handle,WM_TEST,5,LongWord(@pdata[0]));
end;这段代码本身就有问题,pdate 是局部变量,从函数中退出后就被释放掉了,而PostMessage发送消息后立即返回,但是,返回并不代表该消息已经被处理,很有可能等消息被处理的时候,pdate已经被释放掉了,从而在消息处理函数中出现内存错误。
procedure TForm1.btn1Click(Sender: TObject);
var
pb: PChar;
i: Integer;
tmp: Pointer;
begin
pb := nil;
pb := GetMemory(5 * SizeOf(Char));
FillChar(pb[0], SizeOf(pb), #0);
for i := 0 to 4 do
begin s
Pb[i] := Char(i + Ord('A'));
end;
SendMessage(Handle, WM_CopyPointer, 5, Integer(pb));
Dec(Integer(pb), 5 * SizeOf(Char));
FreeMemory(pb);
end;procedure TForm1.ResponseCopyPointer(var AMsg: TMessage);
var
pb: PChar;
I: Integer;
begin
pb := GetMemory(5 * SizeOf(Char));
FillChar(pb[0], SizeOf(pb), #0);
CopyMemory(pb, Pointer(AMsg.LParam), AMsg.WParam);
for i := 0 to AMsg.WParam - 1 do
begin
ShowMessage(pb[i]);
end;
Dec(pb, SizeOf(Char) * 5);
FreeMemory(pb);
end;
这是我写的,用PChar简单多了吧。
procedure TForm1.btn1Click(Sender: TObject);
var
pb: PByte;
i: Integer;
tmp: Pointer;
begin
pb := nil;
pb := GetMemory(5 * SizeOf(Char));
FillChar(PChar(pb)[0], SizeOf(pb), #0);
for i := 0 to 4 do
begin
PChar(Pb)[i] := Char(i + Ord('A'));
end;
SendMessage(Handle, WM_CopyPointer, 5, Integer(pb));
Dec(Integer(PChar(pb)), 5 * SizeOf(Char));
FreeMemory(pb);
end;procedure TForm1.ResponseCopyPointer(var AMsg: TMessage);
var
pb: PByte;
I: Integer;
begin
pb := GetMemory(5 * SizeOf(Char));
FillChar(PChar(pb)[0], SizeOf(pb), #0);
CopyMemory(pb, Pointer(AMsg.LParam), AMsg.WParam);
for i := 0 to AMsg.WParam - 1 do
begin
ShowMessage(Format('%d', [Ord(PChar(pb)[i])]));
end;
Dec(PChar(pb), SizeOf(Char) * 5);
FreeMemory(pb);
end;
//输出65,66,67,68,69