C/C++中容易造成缓冲区溢出的函数

1、strcpy():字符串复制

2、strcat():字符串连接

3、gets():从输入流读取字符串到缓冲区

4、sprintf():打印字符串到缓冲区

5、vsprintf():打印字符串到缓冲区

6、scanf系列:从输入流读取格式化字符

7、strdup():字符串复制


1、strcpy():字符串复制

  • 原型:char *strcpy(char *dest, const char *src);
  • 功能:把src所指由'\0'结束的字符串复制到dest所指的数组中。
  • 说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。
  • 返回:指向dest的指针。

    当src串长度>dest串长度时,程序仍会将整个src串复制到dest区域,可是dest数组已发生溢出。因此会导致dest栈空间溢出以致产生崩溃异常。

2、strcat():字符串连接

  • 函数原型:char* strcat(char* des, char* src)。
  • 函数功能:把src所指向的字符添加到dest结尾处(覆盖原dest结尾处的'\0'),并添加新的'\0'。
  • 说明:des 和 src 所指内存区域不可以重叠且 des 必须有足够的空间来容纳 src 的字符串。
  • 返回值:指向des的指针

    strcat函数常见的错误就是数组越界,即两个字符串连接后,长度超过第一个字符串数组定义的长度,导致越界。

3、gets():从输入流读取字符串到缓冲区

  • 函数原型:char *gets(char *string)
  • 函数功能:从输入流中读取字符串存在string中
  • 返回值:若成功则返回string的指针,否则返回NULL。

    注意:由于gets()不检查字符串string的大小,必须遇到换行符或文件结尾才会结束输入,因此容易造成缓存溢出的安全性问题,导致程序崩溃,可以使用fgets()代替。

4、sprintf():打印字符串到缓冲区

  • 函数原型:int sprintf( char *buffer, const char *format [, argument,...] )
  • 函数功能:sprintf与printf函数的区别:二者功能相似,但是sprintf函数打印到字符串中,而printf函数打印输出到屏幕上
  • 返回值:成功则返回参数buffer字符串长度,失败则返回-1,错误原因存于errno 中。

注意:C语言对数组进行操作时并不检测数组的长度,如果buffer的长度不够,sprintf()很容易造成缓冲区溢出,带来意想不到的后果。使用snprintf()来代替sprintf()将能够很好的解决这个问题。

5、vsprintf():打印字符串到缓冲区

  • 函数原型:int vsprintf(char *str, const char *format, va_list arg)
  • 函数功能:根据参数format 字符串来转换并格式化数据, 然后将结果复制到参数str 所指的字符串数组, 直到出现字符串结束('\0')为止,它们可以用直接的方式模仿 strcpy() 行为。
  • 返回值:如果成功,则返回写入的字符总数,否则返回一个负数。

 注意:由于不检查字符串长度,这个函数也容易造成缓冲区溢出。

6、scanf系列:从输入流读取格式化字符

    scanf系列的函数也设计得很差。在这种情况下,目的地缓冲区会发生溢出。

  • scanf():从控制台输入 ,函数原型:int scanf(格式化字符串,输入列表);
  • sscanf():  从指定字符串输入,函数原型:int sscanf(字符串指针, 格式化字符串, 输入列表 );
  • fscanf() :从文件输入 ,函数原型:int fscanf(文件指针,格式字符串,输入列表);
  • vfscanf() : 在fscanf基础上增加了一个参数:va_list  
  • vscanf(): 在scanf基础上增加了一个参数 :va_list  
  • vsscanf():在sscanf基础上增加了一个参数 :va_list  

7、strdup():字符串复制

  • 函数原型:char *strdup(const char *s);
  • 函数功能:拷贝字符串s的一个副本,由函数返回值返回,这个副本有自己的内存空间,和s没有关联。strdup函数复制一个字符串,使用完后,要使用delete函数删除在函数中动态申请的内存,strdup函数的参数不能为NULL,一旦为NULL,就会报段错误,因为该函数包括了strlen函数,而该函数参数不能是NULL。
  • 返回值:返回拷贝的字符串地址

    strdup()的源码如下:

char * __strdup(const char *s)
{
   size_t  len = strlen(s) +1;
   void *new = malloc(len);
   if (new == NULL)
      return NULL;
   return (char *)memecpy(new,s,len);
}

    strdup会自动分配内存空间,并复制字符串。但strdup只malloc了内存,并没有释放。释放strdup内部动态分配的内存需要由调用者去做,如果调用者忘记free,则容易造成内存泄露。strdup与strcpy函数的区别如下:

  • strcpy函数:把从src地址开始且含有NULL结束符的字符串复制到以dest开始的地址空间
  • strdup函数返回指向被复制的字符串的指针,所需空间由malloc()函数分配且可以由free()函数释放。
  • stdrup可以直接把要复制的内容复制给没有初始化的指针,因为它会自动分配空间给目的指针。strcpy的目的指针一定是已经分配好的内存指针。

参考:https://blog.csdn.net/eastlhu/article/details/28302647

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值