• C++string函数之strcpy_s


    strcpy_s和strcpy()函数的功能几乎是一样的。strcpy函数,就象gets函数一样,它没有方法来保证有效的缓冲区尺寸,所以它只能假定缓冲足够大来容纳要拷贝的字符串。在程序运行时,这将导致不可预料的行为。用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结束符的工作。

    正确用法:

    int n = 6;
      char **argsmy = new char *[n];
      int maxlen = 600;
      for(int i = 0; i < n; i ++)
      {
       argsmy[i] = new char [maxlen];// args[i];
      }
       strcpy_s(argsmy[1],maxlen,"e");
      strcpy_s(argsmy[2],maxlen,"Lzma_");
      strcat_s(argsmy[2], 600, cTAppEncTop.getBitstreamFile());
      strcpy_s(argsmy[3],maxlen,"-BS12");
      strcpy_s(argsmy[4],maxlen,"-CN0");
      strcpy_s(argsmy[5],maxlen,"-d15");
    错误用法:
    argsmy[2] = "Lzma_"; strcpy_s(argsmy[2],maxlen,"see");

    原因:

    argsmy[2] = "Lzma_"; //因为 argsmy[2] 是个指针。他指向一块分配的空间 ,长度 maxlen。

    而这样赋值后,指针指向位置变了。而再strcpy_s(argsmy[2],maxlen,"see"); 实际上是将常数变量空间强制赋值。因此出问题。

    strcpy_s 用法:
    errno_t strcpy_s( 
      char *strDestination, 
      size_t numberOfElements, 
      const char *strSource 
    ); 
    
    template <size_t size> 
    errno_t strcpy_s( 
      char (&strDestination)[size], 
      const char *strSource 
    ); // C++ only
    例子:
    // crt_strcpy_s.cpp
    // This program uses strcpy_s and strcat_s
    // to build a phrase.
    //
    
    #include <string.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <errno.h>
    
    int main( void )
    {
       char string[80];
       // using template versions of strcpy_s and strcat_s:
       strcpy_s( string, "Hello world from " );
       strcat_s( string, "strcpy_s " );
       strcat_s( string, "and " );
       // of course we can supply the size explicitly if we want to:
       strcat_s( string, _countof(string), "strcat_s!" );
       
       printf( "String = %s/n", string );
    }
  • 相关阅读:
    队列与双向队列

    linux nohup, jobs, fg, tail指令 指令前后台切换
    linux shell
    Linux学习笔记四 grep, sed, awk
    面试要求
    jenkins send files or publish
    mysql导入脚本
    第三方接口调用框架
    pdm文件name与comment互相同步
  • 原文地址:https://www.cnblogs.com/djzny/p/4476221.html
Copyright © 2020-2023  润新知