1. 前情提要
- 如题,最近项目程序里使用zmq通信,原意是要将一个vector<vector<Point>>类型的数据结构从Req发送到ReP端,然后对其进行操作。但是本人试过之后发现一旦将其打包好,发送过去,另一端无法访问到内层结构及数据,(相当于传了一个黑盒过去,而自己却需要内部的数据。。。)可能需要处理把整个结构完好无损的发过去才能访问到吧。无奈本人才疏学浅,不知道要怎么打包整个结构。有幸看到这里的大佬如果有想法还请不吝赐教!!!
- 再说回来,不会怎么办呢,来个曲线救国,我把整个结构给它压缩成了一维:
int *rawData = new int[num];
像这样,new了一个指针数组,把所有数据都由这个指针数组来指向。然后将指针数组发送过去,实现间接访问。
2. memcpy函数
函数原型
void *memcpy(void*dest, const void *src, size_t n);
函数源码
void* MyMemcpy(void* dest,const void* src,size_t num)
{
assert(dest&&src);
char* dest_t=(char*)dest;//目标字符串
const char* src_t=(const char*)src;//源字符串
while(num--)
{
*dest_t++= *src_t++;
}
return dest;
}
//(不能解决内存重叠的问题,正序拷贝,适用于任何类型)
功能
由src指向地址为起始地址的连续n个字节的数据复制到以destin指向地址为起始地址的空间内。
说明
1.source和destin所指内存区域不能重叠,函数返回指向destin的指针。
2.与strcpy相比,memcpy并不是遇到’\0’就结束,而是一定会拷贝完n个字节。
3.memcpy用来做内存拷贝,你可以拿它拷贝任何数据类型的对象,可以指定拷贝的数据长度;
4. 要注意,它是以字节为单位一个一个拷贝!!!(不幸跌入这个坑)
5. memcpy函数没有处理内存重叠问题,要注意。
3. 顺带记录一下邻居memmove函数
众所周知,这两个函数最大的不同就是一个需要程序员自己控制内存,不能重叠,否则会出错;另一个即memmove函数则解决了这个内存区域重叠的问题。
memmove函数原理
void* memmove(void* dest, const void* src, size_t n)
{
char * d = (char*) dest;
const char * s = (const char*) src;
assert(dest&&src);
if (s>d)
{
// 无内存重叠,从低地址拷贝
while (n--)
*d++ = *s++;
}
else if (s<d)
{
// 有内存重叠,从高地址拷贝,将指针调到最后
d = d+n-1;
s = s+n-1;
while (n--)
*d-- = *s--;
}
return dest;
}
在此不做过多介绍,文末附上大佬链接,感兴趣的可以去研究。
4. 坑
我定义并初始化的这个指针数组,假设长度为nLength。我在zmq的发送端Req通过指针传参是这样复制的:
void CRequest::SendRequest(int* rawData, int nLength)
{
void *context = zmq_init(1);
void *z_socket = zmq_socket(context, ZMQ_REQ);
// 绑定ip端口
string strConInfo = m_strConInfo;
zmq_connect(z_socket, strConInfo.c_str()); //建立ip+端口连接
//发送部分
zmq_msg_t send_msg;
//方式1——错误
//int nRc = zmq_msg_init_size(&send_msg, nLength);//初始化指令信息
//memcpy((int *)zmq_msg_data(&send_msg), rawData, nLength);//拷贝
//方式1——改正
//int nRc = zmq_msg_init_size(&send_msg, nLength*4);//初始化指令信息
//memcpy((int *)zmq_msg_data(&send_msg), rawData, nLength*4);
//方式2
int nRc = zmq_msg_init_data(&send_msg, rawData, nLength, NULL, NULL);//错误
//int nRc = zmq_msg_init_data(&send_msg, rawData, nLength*4, NULL, NULL);//改正
zmq_msg_send(&send_msg, z_socket, 0); //发送请求
zmq_msg_close(&send_msg);
//接收部分,略
...
zmq_close(z_socket);
zmq_term(context);
}
两种方式本质都是一样的,这里由于是基于字节拷贝的,一直没注意到,导致把长度作为size。发到另一端后,遍历指针数组时,后面部分数据输出直接一堆乱码。代码庞大,检查了好久快要躺尸时,最终定位到了这里,害。
5. 解决
解决办法就很明了了,将nLength*4,(int型是4字节),当然在接收端遍历时也要再除以4恢复指针数组的长度。
————
有时候,一个问题没解决前觉得怎么这么难,可真当解决了吧,又觉得这么简单怎么就没想到,可真让人头大。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/157393.html