64位进程和32位进程通信问题,接收方接收到的数据错误

项目场景:

最近遇到一个问题,64位程序向32位程序发送一个WM_COPYDATA消息传递指针字符串, 发现传递的数据和收到的数据不一致。同样代码,64位程序编译成32位再发送消息的话,能正常收到数据。


问题描述

接收方和发送方的主体代码如下

发送方(64位程序)

// 消息构造体
typedef struct tagCOPYDATASTRUCT {
    ULONG_PTR dwData; //用户定义数据
    DWORD cbData; //用户定义数据的长度
    __field_bcount(cbData) PVOID lpData; //指向用户定义数据的指针
} COPYDATASTRUCT, *PCOPYDATASTRUCT;
// 消息发送函数实现
void CSendDlg::OnDataSend()
{
    CWnd *pWnd = CWnd::FindWindow(NULL,"接收窗口的标题");

    TCHAR msg[255] = "HELLO";
    COPYDATASTRUCT cpd;
    cpd.dwData = 0;
    cpd.cbData = 255 + 1;//多加一个长度,防止乱码
    cpd.lpData = @msg;
    pWnd->SendMessage(WM_COPYDATA,NULL,(LPARAM)&cpd);
}

接收方(32位程序)

// 声明
afx_msg BOOLOnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct);

// 添加消息映射
ON_WM_COPYDATA()

// 函数实现
BOOL CReceiveDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	//return CDialogEx::OnCopyData(pWnd, pCopyDataStruct);

	TCHAR msgReceive[256];
	memset(msgReceive, 0, sizeof(msgReceive));
	wcscpy_s(msgReceive, (TCHAR*)pCopyDataStruct->lpData);

	return CDialogEx::OnCopyData(pWnd, pCopyDataStruct);
}

原因分析:

这个问题是因为64位程序和32位程序在内存地址表示上的差异导致的。在64位程序中指针的大小是8字节,而在32位程序中指针的大小是4字节。当64位程序试图将一个指针发送给32位程序时,它实际上只发送了指针的低4字节,而高4字节则被截断,即指针截断。

假设我们有一个64位指针 0x12345678abcdefgh,这个指针在传递给32位程序时,会被截断为32位指针 0x12345678。这意味着,原本在64位程序中通过该指针可以访问到的内存地址,在32位程序中只能访问到 0x12345678 对应的内存地址。因此,如果32位程序试图通过这个截断后的指针来访问原本64位程序可以访问到的内存地址,就可能会发生访问越界的错误。

在16进制表示法中,一个4字节的指针地址通常表示为8个十六进制数字的序列(每个字节是2个十六进制数字)


解决方案:

可以考虑改变设计,避免直接在消息中传递指针,而是选择传递其他类型的数据。

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值