C++的Memcpy与Memcpy_s函数解析
Memcpy函數(shù)
一. 函數(shù)內(nèi)容
** 1.1函數(shù)原型 **
void * Memcpy(void * dest,const void * src,size_t count)這是一個(gè)函數(shù)指針 接收的是一個(gè)地址 dest是接收地址的首地址,src是源首地址,count是接收目標(biāo)的大小單位為字節(jié) 位于cstring或memcpy.h頭文件中。
使用注意事項(xiàng):
1.-src地址是否為空,
2.-src和dest地址是否重合,是安全重合還是部分重合
3.當(dāng)處與大塊數(shù)據(jù)時(shí)候可能存在,效率低下問題。
改進(jìn)之后的memcpy
void *my_memcpy_byte(void *dst, const void *src, int n) {if (dst == NULL || src == NULL || n <= 0)return NULL;char * pdst = (char *)dst;char * psrc = (char *)src;if (pdst > psrc && pdst < psrc + n){pdst = pdst + n - 1;psrc = psrc + n - 1;while (n--)*pdst-- = *psrc--;}else{while (n--)*pdst++ = *psrc++;}return dst; }linux版本
void *memcpy(void *to, const void *from, size_t n) {void *xto = to;size_t temp, temp1;if (!n)return xto;if ((long)to & 1) {char *cto = to;const char *cfrom = from;*cto++ = *cfrom++;to = cto;from = cfrom;n--;}if (n > 2 && (long)to & 2) {short *sto = to;const short *sfrom = from;*sto++ = *sfrom++;to = sto;from = sfrom;n -= 2;}temp = n >> 2;if (temp) {long *lto = to;const long *lfrom = from; #if defined(CONFIG_M68000) || defined(CONFIG_COLDFIRE)for (; temp; temp--)*lto++ = *lfrom++; #elseasm volatile (" movel %2,%3\n"" andw #7,%3\n"" lsrl #3,%2\n"" negw %3\n"" jmp %%pc@(1f,%3:w:2)\n""4: movel %0@+,%1@+\n"" movel %0@+,%1@+\n"" movel %0@+,%1@+\n"" movel %0@+,%1@+\n"" movel %0@+,%1@+\n"" movel %0@+,%1@+\n"" movel %0@+,%1@+\n"" movel %0@+,%1@+\n""1: dbra %2,4b\n"" clrw %2\n"" subql #1,%2\n"" jpl 4b": "=a" (lfrom), "=a" (lto), "=d" (temp), "=&d" (temp1): "0" (lfrom), "1" (lto), "2" (temp)); #endifto = lto;from = lfrom;}if (n & 2) {short *sto = to;const short *sfrom = from;*sto++ = *sfrom++;to = sto;from = sfrom;}if (n & 1) {char *cto = to;const char *cfrom = from;*cto = *cfrom;}return xto; }二.函數(shù)使用
#include<stdio.h> #include<string.h> int main(void) {char src[]="******************************";char dest[]="abcdefghijlkmnopqrstuvwxyz0123as6";printf("destination before memcpy:%s\n",dest);memcpy(dest,src,strlen(src));printf("destination after memcpy:%s\n",dest);return 0; } ##輸出為destination before memcpy:abcdefghijlkmnopqrstuvwxyz0123as6destination after memcpy: ******************************as6Memcpy_s函數(shù)
void *dest,size_t numberOfElements,const void *src,size_t count );以下是查看其他資料收集出來(lái)的
~~ 第一個(gè)參數(shù)為目標(biāo)內(nèi)存地址,第二個(gè)參數(shù)為目標(biāo)內(nèi)存緩沖大小,第三個(gè)參數(shù)為源內(nèi)存地址,第四個(gè)為源內(nèi)存緩沖的大小。返回值是一個(gè)錯(cuò)誤碼。
為什么這個(gè)返回值是錯(cuò)誤碼呢?因?yàn)檫@個(gè)版本中加入了基本的錯(cuò)誤檢測(cè)。如果源緩沖大小為0,即count為0,函數(shù)返回0,什么也不做。此函數(shù)沒有對(duì)目標(biāo)指針為NULL的情況,不做檢查,所以你自己要注意檢查。如果指針有值,但是是無(wú)效值,函數(shù)也沒辦法檢查是否是有效內(nèi)存,只是會(huì)搜集這些信息,在程序崩潰時(shí)提供調(diào)試需要的信息。
然后檢查源地址是否為空或count是否大于sizeInBytes,兩個(gè)條件有一個(gè)滿足,函數(shù)中先將目標(biāo)內(nèi)存以sizeInBytes指定的大小調(diào)用memset函數(shù)清0.這里可以看出,如果sizeInBytes傳入的大小超出目標(biāo)緩沖區(qū)的大小,也是會(huì)帶來(lái)隱患的,一旦清除了其他進(jìn)程的或者其他線程的內(nèi)存,都是帶來(lái)問題,也很可能導(dǎo)致內(nèi)存操作違規(guī)。所以,第二個(gè)參數(shù)的大小不能超過目標(biāo)緩沖的大小,以字節(jié)為單位。然后程序搜集錯(cuò)誤信息,最后返回錯(cuò)誤碼,并不會(huì)執(zhí)行內(nèi)存復(fù)制的過程。前面說的這是兩個(gè)條件任意一個(gè)進(jìn)入都會(huì)導(dǎo)致失敗,所以在搜集信息時(shí),程序會(huì)對(duì)進(jìn)入的條件進(jìn)行判斷,然后進(jìn)行搜集。
只有這些檢查通過,才會(huì)調(diào)用memcpy函數(shù)執(zhí)行內(nèi)存復(fù)制過程。而第二個(gè)參數(shù)只是內(nèi)部用來(lái)檢測(cè)和清除目標(biāo)內(nèi)存而使用的。
函數(shù)memcpy_s執(zhí)行完畢后返回0,所以檢查返回值是否為0不能判斷是否成功。但是返回值為非零那就是失敗了。
雖然說加上_s版本的函數(shù)是安全版本,但是也是會(huì)出現(xiàn)問題的,使用時(shí)也要注意,即使有時(shí)候不崩潰,但是一旦改寫了其他的線程的內(nèi)存,必然導(dǎo)致程序運(yùn)行不正常,因?yàn)榫€程的數(shù)據(jù)被破壞,至少邏輯會(huì)出錯(cuò)。
不過,_s版本函數(shù)提供了一定的檢測(cè),并且在release版本也可以報(bào)錯(cuò),可以進(jìn)一步調(diào)試問題,而memcpy則在release版本中不會(huì)報(bào)錯(cuò) ~~
總結(jié)
以上是生活随笔為你收集整理的C++的Memcpy与Memcpy_s函数解析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎样将Win10自带的Photos查看器
- 下一篇: VMware虚拟机VMware Auth