C运行库中的安全字符串处理函数
通常,修改字符串的函数都存在一个安全隐患,即目标字符串的缓冲不够大,则会导致内存中的数据被破坏。
例如:
WCHAR szbuffer[3]=L"";
wcscpy(szbuffer,L"abc");
以上的例子是以0结尾的,需要szbuffer[4]才可以容纳。但编译时并不会有任何报错或警告。
针对以上问题,我们必须使用“安全字符串处理函数”,这一类的函数以_s结尾(secure之意),我们来看一下这类函数的原型.
PTSTR _tcscpy(PTSTR strDestination,PCTSTR strSource);
errno_t _tcscpy_s(PTSTR strDestination,size_t numberOfCharacters,PCTSTR strSource);
PTSTR _tcscat(PTSTR strDestination,PCTSTR strSource);
errno_t _tcscat_s(PTSTR strDestination,size_t numberOfCharacters,PCTSTR strSource);
可以看到,在将一个缓冲区作为目标缓冲区时,必须提供这个缓冲区的大小(可容纳的字符个数),通过调用_countof宏计算出来。
这个缓冲区大小参数的主要任务就是验证缓冲区是否足以容纳结果数据.
现在,我们调用这些安全函数的时候,就可以检查返回的errno_t值。只有返回S_OK值,才表明函数调用成功。其他的值可以参照errno.h中的定义。
来看一个例子:
TCHAR szbuffer[3]=L"";
_tcscpy_s(szbuffer,_countof(szbuffer),_T("abc"));
执行完后, szbuffer的第一个字符被设置为'/0',而其他所有字节全部被设置为0xfd(填充符)。
在处理字符串时获得更多的控制
除了安全字符串处理函数,c运行库还增加了一些函数,用于在处理字符串时获得更多的控制。例如,可以控制如何截断字符串。
这类函数具有两个版本,对应ansi和unicode。
HRESULT StringCchCat( LPTSTR pszDest,size_t cchDest,LPCTSTR pszSrc);
HRESULT StringCchCatEx( LPTSTR pszDest,size_t cchDest, LPCTSTR pszSrc,LPTSTR *ppszDestEnd,size_t *pcchRemaining,DWORD dwFlags);
HRESULT StringCchCopy( LPTSTR pszDest,size_t cchDest, LPCTSTR pszSrc);
HRESULT StringCchCopyEx(LPTSTR pszDest,size_t cchDest, LPCTSTR pszSrc, LPTSTR *ppszDestEnd,size_t *pcchRemaining,DWORD dwFlags);
可以看出,在所有方法的名称中,都含有一个“Cch”,这表示count of characters,即字符个数。通常使用_countof宏获得。
另外还有一些函数含有“cb”,这表示函数要求用字节数来指定大小。通常使用sizeof()获得。
这些函数返回HRESULT,具体的值
S_OK | 成功。目标缓冲区中包含源字符串,并以/0终止 |
STRSAFE_E_INVALID_PARAMETER | 失败。将NULL传给了一个参数 |
STRSAFE_E_INSUFFICIENT_BUFFER | 失败。指定的目标缓冲区太小,无法容纳整个源字符串 |
不同于安全字符串处理函数,这类函数运行时,当缓冲区太小,则会执行截断。