当前位置: 首页 > news >正文

更安全的C gets()和str* 以及fgets和strcspn的用法

#include <stdio.h>int main()
{char *str;gets(str);puts(str);return(0);
}

可以说全是错误
首先char *str没有指向一个分配好的地址,就直接读入,危险

ps:
怎么理解char *str = "Hello World"
是将一个存储在一个只读的数据段中字符串常量"Hello World"的首地址赋值给了str

gets(str); 尝试从标准输入读取一个字符串并存储在 str 指向的位置。但是,由于 str 没有被初始化为指向有效的内存,gets 函数可能会尝试写入一个随机的内存地址,这会导致程序崩溃或更糟糕的后果。
puts(str); 试图打印从 gets 读取的字符串。但是,由于 gets 可能导致未定义行为,str 指向的内容可能是不确定的,所以 puts 的行为也是不确定的。

更糟糕的是,gets 函数已被认为是不安全的,并且在 C11 标准中已被移除,因为它不提供任何方式来防止缓冲区溢出。如果输入的数据超过了 str 实际指向的缓冲区的大小,就会发生缓冲区溢出,这可能导致程序崩溃、数据损坏或更严重的安全漏洞(如栈溢出攻击)。

为了避免这种危害,你应该:

使用 malloc 或其他动态内存分配函数为字符串分配内存,并确保 str 指向这块内存。
使用 fgets 替代 gets,因为 fgets 允许你指定一个缓冲区大小,从而防止缓冲区溢出。

关于fgets

char *fgets(char *str, int n, FILE *stream);

str:指向一个字符数组的指针,用于存储读取的数据。
n:要读取的最大字符数(包括结尾的空字符 \0)。
stream:指向 FILE 对象的指针,指定要从中读取数据的输入流。

fgets 函数返回一个指向 str 的指针,如果发生错误或达到文件末尾,则返回 NULL。读取的数据包括任何结尾的换行符(如果存在的话),并且字符串总是以空字符 \0 结尾。

#include <stdio.h>  #define MAX_INPUT 100 // 定义输入的最大长度  int main() {  char str[MAX_INPUT];  // 从标准输入读取一行,最多读取 MAX_INPUT - 1 个字符,保留一个位置给空字符  if (fgets(str, MAX_INPUT, stdin) != NULL) {  // 移除可能的换行符  str[strcspn(str, "\n")] = 0;  puts(str);  } else {  printf("Failed to read input.\n");  }  return 0;  
}

strcspn 代表 “string character span”(字符串字符跨度)

在这里插入图片描述

相关文章:

  • 【基础CSS】
  • 3.Windows下安装MongoDB和Compass教程
  • JavaScprit之初识面向对象
  • 用所有语言写“Hello, World!“
  • WebRTC:真正了解 RTP 和 RTCP
  • C++从零开始(day52)——unordered_set,unordered_map学习使用
  • Visual Studio项目模板的创建与使用
  • 基于 K8s 容器集群的容灾架构与方案
  • (每日持续更新)jdk api之StringBufferInputStream基础、应用、实战
  • 淘宝基于Nginx二次开发的Tengine服务器
  • 「SpringBrick快速入门指南」:一款基于Spring Boot的高级插件化开发框架
  • SQLite优化实践:数据库设计、索引、查询和分库分表策略
  • 媒体发稿:澳门媒体发稿7个流程
  • java组合模式揭秘:如何构建可扩展的树形结构
  • Redis远程连接本机——Docker
  • [ JavaScript ] 数据结构与算法 —— 链表
  • 【Amaple教程】5. 插件
  • 【跃迁之路】【444天】程序员高效学习方法论探索系列(实验阶段201-2018.04.25)...
  • 2017 年终总结 —— 在路上
  • JavaScript新鲜事·第5期
  • Python_OOP
  • Rancher如何对接Ceph-RBD块存储
  • React的组件模式
  • SpringCloud(第 039 篇)链接Mysql数据库,通过JpaRepository编写数据库访问
  • Terraform入门 - 1. 安装Terraform
  • 闭包--闭包之tab栏切换(四)
  • 从重复到重用
  • 分布式任务队列Celery
  • 服务器之间,相同帐号,实现免密钥登录
  • 基于webpack 的 vue 多页架构
  • 解析 Webpack中import、require、按需加载的执行过程
  • 看域名解析域名安全对SEO的影响
  • 前端每日实战 2018 年 7 月份项目汇总(共 29 个项目)
  • 如何使用Mybatis第三方插件--PageHelper实现分页操作
  • 微服务框架lagom
  • 微服务入门【系列视频课程】
  • 为什么要用IPython/Jupyter?
  • 一起来学SpringBoot | 第十篇:使用Spring Cache集成Redis
  • ionic入门之数据绑定显示-1
  • LIGO、Virgo第三轮探测告捷,同时探测到一对黑洞合并产生的引力波事件 ...
  • 分布式关系型数据库服务 DRDS 支持显示的 Prepare 及逻辑库锁功能等多项能力 ...
  • #微信小程序:微信小程序常见的配置传值
  • (分类)KNN算法- 参数调优
  • (附源码)springboot“微印象”在线打印预约系统 毕业设计 061642
  • (力扣记录)235. 二叉搜索树的最近公共祖先
  • (亲测)设​置​m​y​e​c​l​i​p​s​e​打​开​默​认​工​作​空​间...
  • (原創) 如何動態建立二維陣列(多維陣列)? (.NET) (C#)
  • *上位机的定义
  • .htaccess配置重写url引擎
  • .NET MVC、 WebAPI、 WebService【ws】、NVVM、WCF、Remoting
  • .net 程序 换成 java,NET程序员如何转行为J2EE之java基础上(9)
  • .NET 设计一套高性能的弱事件机制
  • .NetCore部署微服务(二)
  • .sdf和.msp文件读取
  • @html.ActionLink的几种参数格式