關於strcpy_s的使用


strcpy_s是strcpy的安全版本,它之所以安全,是因為其在拷貝字符串的時候會有越界的檢查工作。以下是strcpy_s的實現代碼,在tcscpy_s.inl文件可以找到:

/***
*tcscpy_s.inl - general implementation of _tcscpy_s
*
*       Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
*       This file contains the general algorithm for strcpy_s and its variants.
*
****/

_FUNC_PROLOGUE
errno_t __cdecl _FUNC_NAME(_CHAR *_DEST, size_t _SIZE, const _CHAR *_SRC)
{
    _CHAR *p;
    size_t available;

    /* validation section */
    _VALIDATE_STRING(_DEST, _SIZE);
    _VALIDATE_POINTER_RESET_STRING(_SRC, _DEST, _SIZE);

    p = _DEST;
    available = _SIZE;
    while ((*p++ = *_SRC++) != 0 && --available > 0)
    {
    }

    if (available == 0)
    {
        _RESET_STRING(_DEST, _SIZE);
        _RETURN_BUFFER_TOO_SMALL(_DEST, _SIZE);
    }
    _FILL_STRING(_DEST, _SIZE, _SIZE - available + 1);
    _RETURN_NO_ERROR;
}

_VALIDATE_STRING應該是驗證字符串的合法性,是否以null結尾。

_VALIDATE_POINTER_RESET_STRING應該是記錄字符串的原始信息,以便拷貝失敗以后恢復。

當目的地空間不夠時,會根據_VALIDATE_POINTER_RESET_STRING記錄的信息恢復字符串,並且(在Debug模式下)以彈出對話框的形式報告錯誤。

_FILL_STRING完成在字符串最后加上null結束符的工作。以前沒有注意到這一點,所以犯了一個以下的錯誤,先看源代碼:

const int ALLOC_GRANULARITY = 64 * 1024;	//分配粒度:64K

//隨機產生一個指定范圍內的隨機數
inline int RandomGen(int nMin, int nMax)
{
	return (rand() % (nMax - nMin + 1) + nMin); 
}


int _tmain(int argc, _TCHAR* argv[])
{
	srand((unsigned)time(NULL));
	char *pBuf = new char[ALLOC_GRANULARITY];		//緩存
	
	//讀取500個單詞到vector
	vector<string> vecWord;		//存放單詞的vector

	//省略讀取F:\\hp1.txt文件中的單詞並存放在vector中的代碼。。。。

	//fill the buffer
	string str;
	char *p = pBuf;
	str = vecWord[RandomGen(0, nWordNum-1)];		//get a string from the vector randomly
	while ((p+str.length()) < pBuf + ALLOC_GRANULARITY)
	{	
		//copy string into the buffer
		strcpy_s(p, str.length()+1, str.c_str());
		//set pointer p to the end of the string
		p += str.length();
		//把單詞最后一個null符號用空格覆蓋,然后指針前移,否則會導致pBuf指向的字符串始終是第一個得到的字符串
		*p++ = ' ';
		str = vecWord[RandomGen(0, nWordNum-1)];	//get a string from the vector randomly
	}
	vecWord.clear();
	
	//省略寫文件的代碼。。。。

	delete pBuf;
	return 0;
}

以上需要的地方有如下幾點:

1. string::c_str()返回的const char*是包含null結束符的,所以在使用strcpy_s需要在第二個參數指定緩沖區大小的時候加上1,因為string::length()返回的長度是不包括null結束符的

2. 要把每個單詞都保存進pBuf中,還需要把每個單詞的null結束符先覆蓋掉,否則從pBuf讀取字符串的時候只會讀取到第一個存入的單詞。所以這兩行代碼很重要:

//set pointer p to the end of the string
p += str.length();
//把單詞最后一個null符號用空格覆蓋,然后指針前移,否則會導致pBuf指向的字符串始終是第一個得到的字符串
*p++ = ' ';


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM