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

在写windows C++代码的时候,从代码安全角度考虑,我们应该注意什么?

        在写windows C++代码的时候,从代码安全角度考虑,我们应该注意什么?分别是:输入验证、内存管理、错误处理、并发和线程安全、使用安全的API、避免使用不安全的函数、最小权限原则。

一、输入验证

1. 用户输入验证

#include <iostream>
#include <string>
#include <limits>int main() {int age;while (true) {std::cout << "请输入您的年龄: ";if (std::cin >> age && age > 0 && age < 130) {break;} else {std::cout << "无效输入,请重新输入。\n";std::cin.clear(); // 清除失败的输入std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // 忽略错误输入之后的字符}}std::cout << "输入的年龄是: " << age << std::endl;return 0;
}

2. 文件读取验证

        当从文件中读取数据时,您需要验证文件是否存在,是否可以被打开,以及读取的数据是否符合预期格式。例如,读取一个存储数字的文件:

#include <fstream>
#include <iostream>
#include <vector>int main() {std::ifstream file("numbers.txt");std::vector<int> numbers;int number;if (!file) {std::cerr << "无法打开文件" << std::endl;return 1;}while (file >> number) {numbers.push_back(number);}if (!file.eof()) {std::cerr << "文件读取过程中发生错误" << std::endl;return 1;}std::cout << "读取到的数字有: ";for (int num : numbers) {std::cout << num << " ";}std::cout << std::endl;return 0;
}

3. 网络数据接收验证

        在处理网络通信时,接收到的数据应该经过严格验证。例如,如果您的程序是一个服务器,它可能需要验证从客户端接收到的消息格式是否正确:

// 假设这是一个简单的TCP服务器接收数据的代码片段
char buffer[1024];
int receivedBytes = recv(clientSocket, buffer, 1024, 0);
if (receivedBytes > 0) {// 验证接收到的数据if (isValidMessage(buffer, receivedBytes)) {// 处理消息} else {std::cerr << "接收到无效的消息格式" << std::endl;}
}

二、内存管理

1. 使用裸指针管理动态内存(传统方法)

int* ptr = new int(10); // 分配内存
// 使用 ptr...
delete ptr; // 释放内存
ptr = nullptr; // 防止悬挂指针

        在这个例子中,必须确保在 ptr 不再需要时释放分配的内存,并将指针设为 nullptr 以避免悬挂指针。这种方法容易出错,因为需要手动管理内存。

2. 使用智能指针管理动态内存(现代方法)

        C++11 引入的智能指针(如 std::unique_ptrstd::shared_ptr)自动管理内存,可以减少内存泄漏的风险。

#include <memory>std::unique_ptr<int> ptr(new int(10));
// 使用 ptr...
// 不需要手动释放内存,当 ptr 离开作用域时,内存会自动被释放

3. 防止数组越界

4. 避免内存泄漏

void function() {int* ptr = new int(10); // 分配内存// 函数的其他操作...delete ptr; // 释放内存
}

        如果函数中有多个返回路径或可能抛出异常,使用智能指针来保证内存在任何情况下都能被正确释放。

三、错误处理机制

1. 使用异常处理机制

        C++ 提供了异常处理机制,允许在检测到错误时抛出异常,并在上层代码中捕获和处理这些异常。

#include <iostream>
#include <stdexcept>double divide(double a, double b) {if (b == 0) {throw std::invalid_argument("除数不能为0");}return a / b;
}int main() {try {double result = divide(10.0, 0.0);std::cout << "结果: " << result << std::endl;} catch (const std::invalid_argument& e) {std::cerr << "捕获到错误: " << e.what() << std::endl;}return 0;
}

2. 使用返回值进行错误指示

        在某些情况下,使用返回值来指示错误是更加合适的。这种方法常用于 C 风格的代码或者需要保持与旧代码的兼容性。

#include <iostream>bool safeDivide(double a, double b, double& result) {if (b == 0) {return false; // 错误指示}result = a / b;return true; // 操作成功
}int main() {double result;if (!safeDivide(10.0, 0.0, result)) {std::cerr << "错误:除数不能为0" << std::endl;} else {std::cout << "结果: " << result << std::endl;}return 0;
}

3. 使用错误码

四、最小权限原则

        最小权限原则(Principle of Least Privilege, PoLP)是一种安全设计原则,意在确保程序、进程或用户仅具有完成其任务所必需的最小权限集。在 Windows C++ 编程中,这通常涉及到操作系统资源的访问和管理。以下是一些应用最小权限原则的例子:

1. 运行权限限制

        当开发一个应用程序时,确保它以最低必要的权限运行。例如,如果您的程序仅需读取文件,不应请求或具有写入文件的权限。

// 以只读方式打开文件
std::ifstream file("example.txt");
if (!file) {std::cerr << "无法打开文件,权限不足或文件不存在" << std::endl;// 错误处理
}

2. 数据库访问

        当您的程序需要与数据库交互时,为数据库用户分配只能执行其需求的操作的最小权限。例如,如果程序只需要从数据库读取数据,那么数据库用户不应该具有写入、修改或删除数据的权限。

// 假设这是一个数据库连接代码片段
// 这个数据库用户只有读取数据的权限
const char* connectionString = "User=ReadOnlyUser;Password=example;...";

3. 网络服务权限

        如果您的程序是一个网络服务,确保它在一个受限的环境中运行,例如在低权限的用户账户下运行,避免在需要管理员权限的账户下运行。

4. 文件和目录权限

        当您的程序需要创建文件或目录时,设置合理的访问控制列表(ACL),以确保只有必要的用户或程序有权访问这些资源。

五、并发和线程安全

        在并发编程中,线程安全是一个核心考虑因素。线程安全的代码可以在多线程环境中安全地被多个线程同时执行,而不会导致数据损坏或不一致的状态。以下是一些并发和线程安全的例子:

1. 使用互斥锁

        互斥锁(mutex)是保护共享资源免受多个线程同时访问的一种方法。

#include <iostream>
#include <thread>
#include <mutex>std::mutex mtx; // 全局互斥锁
int sharedData = 0; // 共享数据void increment() {mtx.lock(); // 获取锁++sharedData; // 修改共享数据mtx.unlock(); // 释放锁
}int main() {std::thread t1(increment);std::thread t2(increment);t1.join();t2.join();std::cout << "共享数据的值: " << sharedData << std::endl;return 0;
}

2. 使用条件变量

        条件变量是一种允许线程等待特定条件的同步机制。

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>std::mutex mtx;
std::condition_variable cv;
bool ready = false;void printNumber(int num) {std::unique_lock<std::mutex> lck(mtx);while (!ready) {cv.wait(lck);}std::cout << "Number: " << num << std::endl;
}void setReady() {{std::lock_guard<std::mutex> lck(mtx);ready = true;}cv.notify_all();
}int main() {std::thread t1(printNumber, 1);std::thread t2(printNumber, 2);setReady();t1.join();t2.join();return 0;
}

        在这个例子中,两个线程等待 ready 变量变为 true。一旦 setReady 函数被调用,条件变量通知所有等待的线程继续执行。

3. 使用原子操作

        原子操作是不可分割的操作,可以在多线程环境中安全地执行,不需要额外的同步机制。

#include <iostream>
#include <thread>
#include <atomic>std::atomic<int> count(0); // 原子变量void increment() {for (int i = 0; i < 10000; ++i) {count++; // 原子操作}
}int main() {std::thread t1(increment);std::thread t2(increment);t1.join();t2.join();std::cout << "计数: " << count << std::endl;return 0;
}

        在这个例子中,两个线程同时增加一个计数器。由于 count 是一个原子类型,每次增加操作都是线程安全的。

六、使用安全的函数(Windows api)

        这里只需注意需要使用安全的。

1. 字符串复制

char source[] = "Hello World";
char dest[11];
strcpy(dest, source); // 不安全,没有边界检查char source[] = "Hello World";
char dest[11];
strncpy(dest, source, sizeof(dest) - 1); // 安全,指定最大复制长度
dest[sizeof(dest) - 1] = '\0'; // 确保字符串以空字符结尾

strcpy 的问题

  strcpy 函数用于将一个字符串复制到另一个字符串。它继续复制字符直到遇到源字符串的空终止字符('\0')。这个函数的问题在于它不考虑目标字符串的大小。如果源字符串长度超过了目标字符串的容量,strcpy 会继续写入,导致超出目标数组的边界,造成缓冲区溢出。这种溢出可能覆盖其他重要的内存数据,引起程序崩溃或安全漏洞。

        char source[] = "这个字符串很长,超过目标缓冲区的大小"; char dest[10]; // 只有10个字符的空间 strcpy(dest, source); // 危险:源字符串长度超过了dest的容量

        在这个例子中,dest 只能容纳9个字符和一个空终止符,但 source 的长度远远超过这个限制,导致 dest 的边界被溢出。

strncpy 的相对安全性

  strncpy 函数也是用于复制字符串,但它接受一个额外的参数来指定最大复制的字符数。这个函数在到达最大字符数或遇到源字符串的空终止符时停止复制。这有助于防止超出目标数组的边界,如果正确使用的话。

char source[] = "这个字符串很长,可能超过目标缓冲区的大小";
char dest[10];
strncpy(dest, source, sizeof(dest) - 1); // 复制最多9个字符
dest[sizeof(dest) - 1] = '\0'; // 确保有空终止符

strcpy 的问题

strcpy 函数用于将一个字符串复制到另一个字符串。它继续复制字符直到遇到源字符串的空终止字符('\0')。这个函数的问题在于它不考虑目标字符串的大小。如果源字符串长度超过了目标字符串的容量,strcpy 会继续写入,导致超出目标数组的边界,造成缓冲区溢出。这种溢出可能覆盖其他重要的内存数据,引起程序崩溃或安全漏洞。

strncpy 的相对安全性

strncpy 函数也是用于复制字符串,但它接受一个额外的参数来指定最大复制的字符数。这个函数在到达最大字符数或遇到源字符串的空终止符时停止复制。这有助于防止超出目标数组的边界,如果正确使用的话。

例子:使用 strncpy 防止缓冲区溢出

2. 字符串连接

char str[10] = "Hello";
strcat(str, " World"); // 不安全,可能导致缓冲区溢出char str[15] = "Hello";
strncat(str, " World", sizeof(str) - strlen(str) - 1); // 安全,限制最大添加长度

3. 格式化字符串

char buffer[50];
sprintf(buffer, "Value: %d", 123); // 不安全,没有边界检查char buffer[50];
snprintf(buffer, sizeof(buffer), "Value: %d", 123); // 安全,限制最大写入长度

        虽然 strncpystrcpy 安全,但它仍然需要小心使用。如果最大复制长度小于源字符串长度,strncpy 不会自动添加空终止符,可能导致目标字符串没有正确终止。因此,使用 strncpy 时,程序员需要确保目标字符串有足够的空间,并在需要时手动添加空终止符。

 

相关文章:

在写windows C++代码的时候,从代码安全角度考虑,我们应该注意什么?

在写windows C代码的时候&#xff0c;从代码安全角度考虑&#xff0c;我们应该注意什么&#xff1f;分别是&#xff1a;输入验证、内存管理、错误处理、并发和线程安全、使用安全的API、避免使用不安全的函数、最小权限原则。 一、输入验证 1. 用户输入验证 #include <io…...

【草料】uni-app ts vue 小程序 如何如何通过草料生成对应的模块化二维码

一、查看uni-app项目 1、找到路径 可以看到项目从 src-race-pages-group 这个使我们目标的查询页面 下面我们将这个路径copy到草料内 2、找到进入页面入参 一般我们都会选择 onload() 函数下的入参 这里我们参数的是 id 二、草料 建议看完这里的教程文档 十分清晰&#xff01…...

CMS与FullGC

JVM中的CMS&#xff08;Concurrent Mark Sweep&#xff09;GC和Full GC&#xff08;Full Garbage Collection&#xff09;是两种不同的垃圾回收算法。 CMS GC&#xff1a;CMS GC是一种并发的垃圾回收算法&#xff0c;它在运行期间与应用程序线程并发工作&#xff0c;尽可能减少…...

一款.NET开源的小巧、智能、免费的Windows内存清理工具 - WinMemoryCleaner

前言 我们在使用Windows系统的时候经常会遇到一些程序不会释放已分配的内存&#xff0c;从而导致电脑变得缓慢。今天给大家推荐一款.NET开源的小巧、智能、免费的Windows内存清理工具&#xff1a;WinMemoryCleaner。 使用Windows内存清理工具来优化内存&#xff0c;这样不必浪…...

iptables详解:链、表、表链关系、规则的基本使用

目录 防火墙基本概念 什么是防火墙&#xff1f; Netfilter与iptables的关系 链的概念 表的概念 表链关系 规则的概念 查询规则 添加规则 删除iptables中的记录 修改规则 更详细的命令&#xff08;5链4表&#xff09; 防火墙基本概念 什么是防火墙&#xff1f; 在…...

安全管理中心(设备和技术注解)

网络安全等级保护相关标准参考《GB/T 22239-2019 网络安全等级保护基本要求》和《GB/T 28448-2019 网络安全等级保护测评要求》 密码应用安全性相关标准参考《GB/T 39786-2021 信息系统密码应用基本要求》和《GM/T 0115-2021 信息系统密码应用测评要求》 1系统管理 1.1对系统管…...

Failed to execute org.scala-tools:maven-scala-plugin:2.15.2解决

原因也不是很清楚&#xff0c;查看一个博主文章(net.alchim31.maven:scala-maven-plugin&#xff1a;maven依赖无法下载或无法编译)得到的解决方案&#xff1a; 在idea的terminal执行以下语句即可实现maven对scala代码的编译&#xff1a; mvn clean scala:compile compile pac…...

C#中委托和事件的使用总结

委托&#xff08;delegate&#xff09;特别用于实现事件和回调方法。所有的委托&#xff08;Delegate&#xff09;都派生自 System.Delegate 类。事件是一种特殊的多播委托&#xff0c;仅可以从声明事件的类或结构中对其进行调用。类或对象可以通过事件向其他类或对象通知发生的…...

基于STM32的外部中断(EXTI)在嵌入式系统中的应用

外部中断&#xff08;External Interrupt&#xff0c;EXTI&#xff09;是STM32嵌入式系统中常见且重要的功能之一。它允许外部事件&#xff08;例如按键按下、传感器触发等&#xff09;通过适当的引脚触发中断&#xff0c;从而应用于各种嵌入式系统中。在STM32微控制器中&#…...

【心得】PHP的文件上传个人笔记

目录 1 php的文件上传绕过 黑名单绕过 2 php文件上传的00截断 3 iconv字符转换异常后造成了字符截断 4 文件后缀是白名单的时候的绕过 web服务器的解析漏洞绕过 5.高级文件上传绕过 1 .htaccess nginx.htaccess 2 服务端内容检测 3 配合伪协议来绕过 4.配合日志包含绕…...

深度学习之基于Pytorch和OCR的识别文本检测系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介深度学习与OCRPyTorch在OCR中的应用文本检测系统的关键组成部分1. 图像预处理2. 深度学习模型3. 文本检测算法4. 后处理 二、功能三、系统四. 总结 一项目简…...

三十一、W5100S/W5500+RP2040树莓派Pico<TCP_Server多路socket>

文章目录 1 前言2 简介2. 1 使用多路socket的优点2.2 多路socket数据交互原理2.3 多路socket应用场景 3 WIZnet以太网芯片4 多路socket设置示例概述以及使用4.1 流程图4.2 准备工作核心4.3 连接方式4.4 主要代码概述4.5 结果演示 5 注意事项6 相关链接 1 前言 W5100S/W5500是一…...

带你精通chrony服务器

华子目录 为什么会出现Chrony&#xff1f;Linux的两个时钟NTP介绍Chrony介绍安装与配置安装Chrony配置文件分析实验1实验2chronyc命令查看时间服务器chronyc sources输出分析其他命令 常见时区 为什么会出现Chrony&#xff1f; 由于IT系统中&#xff0c;准确的计时非常重要&am…...

vs2017 编译Qt 5.11.2 源码

SDK 10.0.22000.194 有 2种编译方式 &#xff0c;第二种 看下面 方式一: 1、问题描述&#xff1a; 使用VS编译程序时&#xff0c;运行库选择多线程&#xff08;/MT&#xff09;&#xff0c;表示采用多线程静态release的方式进行编译。 但是&#xff0c;发现编译是不能通过的…...

【SpringBoot3+Vue3】四【实战篇】-前端(vue基础)

目录 一、项目前置知识 二、使用vscode创建 三、vue介绍 四、局部使用vue 1、快速入门 1.1 需求 1.2 准备工作 1.3 操作 1.3.1 创建html 1.3.2 创建初始html代码 1.3.3 参照官网import vue 1.3.4 创建vue应用实例 1.3.5 准备div 1.3.6 准备用户数据 1.3.7 通过…...

element ui修改select选择框背景色和边框色

一、修改选择框的背景色和边框色 style部分 .custom-select /deep/ .el-input__inner {color: #fff!important;border: 1px solid #326AFF;background: #04308D !important; } html部分 <el-select class"custom-select" v-model"dhvalue" placeholde…...

软件测试人员提问常用的ChatGPT通用提示词模板

如何设计有效的软件测试用例&#xff1f; 如何运用自动化测试工具进行软件测试&#xff1f; 如何进行软件的功能测试、性能测试和安全测试&#xff1f; 如何评估软件测试的质量和覆盖范围&#xff1f; 软件测试有哪些常见的缺陷和错误&#xff0c;如何识别和解决&#xff1…...

【开源】基于JAVA的服装店库存管理系统

项目编号&#xff1a; S 052 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S052&#xff0c;文末获取源码。} 项目编号&#xff1a;S052&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 角色管理模块2.3 服…...

Jenkins代码检测和本地静态检查

1&#xff1a;Jenkins简介 Jenkins是一个用Java编写的开源的持续集成工具&#xff1b;Jenkins自动化部署可以解决集成、测试、部署等重复性的工作&#xff0c;工具集成的效率明显高于人工操作&#xff1b;并且持续集成可以更早的获取代码变更的信息&#xff0c;从而更早的进入测…...

从0开始学习JavaScript--JavaScript 字符串与文本内容使用

JavaScript中的字符串和文本内容处理是前端开发中的核心技能之一。本文将深入研究字符串的创建、操作&#xff0c;以及文本内容的获取、修改等操作&#xff0c;并通过丰富的示例代码&#xff0c;帮助读者更全面地了解和应用这些概念。 JavaScript 字符串基础 字符串是JavaScr…...

基于算法竞赛的c++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中&#xff0c;结构体可以嵌套使用&#xff0c;形成更复杂的数据结构。例如&#xff0c;可以通过嵌套结构体描述多层级数据关系&#xff1a; struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

Chapter03-Authentication vulnerabilities

文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?

在建筑行业&#xff0c;项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升&#xff0c;传统的管理模式已经难以满足现代工程的需求。过去&#xff0c;许多企业依赖手工记录、口头沟通和分散的信息管理&#xff0c;导致效率低下、成本失控、风险频发。例如&#…...

基础测试工具使用经验

背景 vtune&#xff0c;perf, nsight system等基础测试工具&#xff0c;都是用过的&#xff0c;但是没有记录&#xff0c;都逐渐忘了。所以写这篇博客总结记录一下&#xff0c;只要以后发现新的用法&#xff0c;就记得来编辑补充一下 perf 比较基础的用法&#xff1a; 先改这…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

VTK如何让部分单位不可见

最近遇到一个需求&#xff0c;需要让一个vtkDataSet中的部分单元不可见&#xff0c;查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行&#xff0c;是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示&#xff0c;主要是最后一个参数&#xff0c;透明度…...

解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错

出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上&#xff0c;所以报错&#xff0c;到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本&#xff0c;cu、torch、cp 的版本一定要对…...

Axios请求超时重发机制

Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式&#xff1a; 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

EtherNet/IP转DeviceNet协议网关详解

一&#xff0c;设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络&#xff0c;本网关连接到EtherNet/IP总线中做为从站使用&#xff0c;连接到DeviceNet总线中做为从站使用。 在自动…...