memcpy()的问题

可能丢失字节~



定义函数: void *memcpy(void *dest, const void *src, size_t n)
函数说明: memcpy()用来拷贝src所指的内存内容前n个字节到dest所指的内存地址上。
有个疑问,如果memcpy()调用2次,那么第二次拷贝的内容是追加的还是覆盖的?
=========================================
我用socket传文件,socket缓冲区是有大小限制的,假设缓冲区是1K,那么调用sockClient.Receive(data, 1M)也只能收到前1K数据。接收的时候用循环

......
int dataLength;// 要接收文件的长度
sockClient.Receive(&dataLength, 4);// 接收文件的长度信息
byte *data = new byte[dataLength];//存放接收的文件
....
while (1)
{
byte *t= new byte[0x1000];//循环一次接收的数据
int n = sockClient.Receive(t, 0x1000);
if (n == 0)
{
break; //接收完毕退出
}
memcpy(data, t, n);//把收到的数据写入data

}

这样为什么不行,哪里出问题?要怎么样把循环接收的所有数据都追加到data?
问题补充:发送小的图片没问题,大的图片就出问题,如图,而且接收程序出错退出,什么原因呢?
给data分配的存储空间不够吗?现在data的大小已经是和发送的文件大小一致的了,奇怪了






void *memcpy(void *dest, const void *src, size_t n);
就是把以src指向地址为起始地址连续n个字节的数据复制到dest指向地址为起始地址连续n个字节的空间内。

如果连续调用memcpy但dest参数指向的地址不变的话,那当然就是覆盖数据了。
如果好追加数据,那么每次执行memcpy后要把dest的地址增加到你要追加数据的地址。


你的代码可以改为(请自己保证给data分配足够的存储空间):

int m=0;
while (1)
{
byte *t= new byte[0x1000];//循环一次接收的数据
int n = sockClient.Receive(t, 0x1000);
if (n == 0)
{
break; //接收完毕退出
}
memcpy(data+m*0x1000, t, n);//把收到的数据写入data
m++;
}







标准的MEMCPY是运行速度最快的。
#include

#include

#include



#ifdef WIN32

#include

#else

#include

#include

#endif



double get_time_ms()

{

#ifdef WIN32

return (double)GetTickCount();

#else

struct timeval tv;

struct timezone tz;

gettimeofday (&tv , &tz);

return https://www.360docs.net/doc/ce18215427.html,_sec * 1000 + https://www.360docs.net/doc/ce18215427.html,_usec / 1000 ;

#endif

}



//这是微软公开的crt src文件夹内的源代码:

void * memcpy_1 (void * dst, void * src , size_t n)

{

void * ret = dst;

while (n--) {

*(char *)dst = *(char *)src;

dst = (char *)dst + 1;

src = (char *)src + 1;

}

return ret;

}





//这是我写的,按照最近流行的优化方式做的

void * memcpy_2 (void * dst, void * src , size_t n)

{


void * ret = dst;

size_t l = n>>2;

while (l--) {

*(size_t *)dst = *(size_t *)src;

dst = (size_t *)dst + 1;

src = (size_t *)src + 1;

}

l = n & 3;

while (l--) {

*(char *)dst = *(char *)src;

dst = (char *)dst + 1;

src = (char *)src + 1;

}

return ret;

}



void main(int argc, char ** argv)

{

const int cstMemSize = 0x2FFFFFF;



if(argc<2)

{

printf("请输入参数 [ 0 | 1 | 2 | 3] ");

return ;

}



char * str = (char*)malloc(cstMemSize);

char * str2 = (char*)malloc(cstMemSize+16);



size_t t1 = get_time_ms();



switch(argv[1][0])

{

case '0': memcpy(str, str2, cstMemSize );

break;

case '1': memcpy_1(str, str2, cstMemSize );

break;

case '2': memcpy_2(str, str2, cstMemSize );

break;

case '3': memcpy_2(str, str2+1, cstMemSize ); //考虑字节不对齐的情况

break;

}





double t2 = get_time_ms();

free(str);

free(str2);

printf("memset_%c %f\n", argv[1][0] ,t2-t1);



}
复制代码

在windows xp/vc6环境下:

结果发现memcpy_1是最慢的,当然,这是串操作,当然很慢;
但是直接调用memcpy函数是最快的,这大概是微软在vc链接程序时做的优化.
而上面memcpy_2的效果一般般,比memcpy_1快,但是不如直接调用memcpy快.


在gcc/freebsd环境下,如果未加优化参数-O2,case '3'的情况速度更慢.我怀疑可能是字节不对齐带来的恶果.
不过,当开启了-O2后,4个case的测试时间差不多了.但是还是gcc自己的memset函数最快.

我现在怀疑,象(int *)这样的奇技淫巧如果使用不当,带来的效果不明显,还不如不用.现实情况是复杂的,编译器比我考虑的多的多

相关主题
相关文档
最新文档