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

掌握assert的使用:断言在错误检查和调试中不可或缺

断言在错误检查和调试中不可或缺

  • 一、简介
  • 二、断言的基本语法和用法
  • 三、错误检查与断言
  • 四、 调试与断言
  • 五、避免滥用断言
  • 六、总结

一、简介

断言是一种在程序中用于检查特定条件是否满足的工具。一般用于验证开发者的假设,如果条件不成立,就会导致程序报错并中止执行。

断言的作用是在开发过程中进行错误检查和调试,确保程序的正确性和稳定性。通过使用断言,在程序运行时立即发现潜在的问题并加以解决,提高代码质量和可靠性。在调试阶段,断言还可以精确定位问题所在,并帮助快速解决bug。因此,掌握断言对于开发过程中的错误检查和调试是不可或缺的。

断言在程序中插入特定的检查点,验证代码中的假设和条件是否满足。如果条件不成立,断言会引发错误并中止程序的执行,立即发现潜在的问题。这种实时的错误检查能够及时发现并修复代码中的bug。
在这里插入图片描述

二、断言的基本语法和用法

在C/C++中使用assert宏来进行断言。在代码中使用断言很简单,只需要在需要进行断言的地方使用assert宏并在括号内写入要检查的条件。assert宏在<assert.h>头文件中定义,使用方法如下:

#include <assert.h>int main() {int x = 5;assert(x == 5); // 断言条件为真,程序继续执行assert(x == 10); // 断言条件为假,程序停止执行并报错return 0;
}

断言条件为假时,assert宏会输出错误信息并终止程序执行。

在C++中,还可以使用断言标准库<cstdlib>中的assert宏,用法与C中的assert宏基本相同:

#include <cstdlib>int main() {int x = 5;assert(x == 5); // 断言条件为真,程序继续执行assert(x == 10); // 断言条件为假,程序停止执行并报错return 0;
}

使用断言宏assert时,主要的参数是断言条件,也就是在运行时需要检查的表达式。当断言条件为 false 时,程序将会产生错误消息并终止执行。

在编译程序时,通过定义 NDEBUG 宏来禁用断言。如果 NDEBUG 被定义,assert 宏将会被替换为一个空操作,这意味着断言将会被忽略,且程序不会因为断言失败而停止执行。

许多编译器也提供了一些优化选项,可以控制是否启用断言以及断言失败时的行为。这些选项通常包括在编译器的参数中,例如 -DNDEBUG 会定义 NDEBUG 宏。

在 C 中,assert 宏已经内置在 <assert.h> 头文件中。在 C++ 中,cassert 头文件提供了对应的 C++ 版本的断言宏,也可以看作是 C 语言里 assert.h 的 C++ 版本。

三、错误检查与断言

在函数中使用断言来检查传入参数和返回值:

#include <cassert>int divide(int numerator, int denominator) {// 检查分母是否为0assert(denominator != 0 && "Denominator cannot be zero");// 计算并返回结果return numerator / denominator;
}int main() {int result = divide(10, 2);assert(result == 5 && "Division result is incorrect");return 0;
}

在类的方法中使用断言来确保数据的合法性:

#include <cassert>class Rectangle {
public:Rectangle(int width, int height) : width_(width), height_(height) {assert(width_ > 0 && "Width must be greater than 0");assert(height_ > 0 && "Height must be greater than 0");}int getArea() {return width_ * height_;}private:int width_;int height_;
};int main() {Rectangle rect(10, 20);int area = rect.getArea();assert(area == 200 && "Area calculation is incorrect");return 0;
}

四、 调试与断言

断言只在Debug模式下起作用,在Release模式下是被禁用的。因此在调试时可以随意使用断言来帮助定位问题,而在发布时,断言不会影响程序的性能。

在调试时使用断言来定位问题:

#include <cassert>// 假设这个函数有一个问题,需要进行调试
int customFunction(int x, int y) {// 假设这里有一些复杂的逻辑int result = x * y + 10;// 在调试时使用断言来检查结果assert(result > 0 && "Result should be greater than 0");return result;
}int main() {int a = 5;int b = 0;int res = customFunction(a, b);// 后续的代码// ...return 0;
}

有效的断言语句:

  1. 明确指定断言条件。

  2. 提供有意义的错误消息。

  3. 不要包含副作用(比如在断言语句中进行修改变量)。

断言在多线程和并发编程中:

  1. 验证共享数据结构的访问是否是线程安全的。

  2. 在使用条件变量等同步机制时,断言可以用来验证条件的正确性。

  3. 死锁检测。

  4. 并发操作的顺序和一致性检查。

线程安全性检查示例:

#include <iostream>
#include <mutex>
#include <cassert>std::mutex g_mutex;
int g_sharedData = 0;void incrementData() {std::lock_guard<std::mutex> lock(g_mutex);g_sharedData++;
}int main() {constexpr int numThreads = 10;std::thread threads[numThreads];for (int i = 0; i < numThreads; ++i) {threads[i] = std::thread(incrementData);}for (int i = 0; i < numThreads; ++i) {threads[i].join();}// 使用断言来验证共享数据的最终值assert(g_sharedData == numThreads);std::cout << "All threads have incremented the shared data.\n";return 0;
}

死锁检测示例:

#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
#include <cassert>std::mutex g_mutex1, g_mutex2;void threadFunc1() {std::lock_guard<std::mutex> lock1(g_mutex1);std::this_thread::sleep_for(std::chrono::seconds(1));std::lock_guard<std::mutex> lock2(g_mutex2); // Absent minded programmer error!// (Thread function 1's work)
}void threadFunc2() {std::lock_guard<std::mutex> lock2(g_mutex2);std::this_thread::sleep_for(std::chrono::seconds(1));std::lock_guard<std::mutex> lock1(g_mutex1); // Absent minded programmer error!// (Thread function 2's work)
}int main() {std::thread t1(threadFunc1);std::thread t2(threadFunc2);t1.join();t2.join();// 此处使用断言来检查程序是否在死锁状态assert(false && "Program should not reach here - potential deadlock!");return 0;
}

五、避免滥用断言

  1. 断言应该用于预期永远不会发生的情况。它不应该用于验证可能会发生的条件或逻辑。

  2. 断言不应该用于参数验证和输入验证。

  3. 断言应该主要用于开发和测试阶段,帮助发现问题和调试程序。在生产环境中,可以通过配置关闭断言以避免额外的开销。

  4. 断言的条件应该是简单和快速的检查,避免在断言中放入复杂的逻辑或长时间运行的代码。

  5. 谨慎使用断言来检测并发问题。

  6. 记得删除或禁用不再需要的断言。

六、总结

  1. 断言可用于在运行时检查程序中的错误,例如检查指针是否为空、数组索引是否有效、除数是否为零等。捕获程序中潜在的bug和错误,以及防止程序崩溃或产生不确定行为。

  2. 断言在调试阶段对程序进行验证和测试时起着重要作用。通过在关键的地方插入断言语句,快速验证程序的不变式、条件和假设是否成立。

  3. 清晰和易于理解的断言可以提高代码的可维护性。

在这里插入图片描述

相关文章:

掌握assert的使用:断言在错误检查和调试中不可或缺

断言在错误检查和调试中不可或缺 一、简介二、断言的基本语法和用法三、错误检查与断言四、 调试与断言五、避免滥用断言六、总结 一、简介 断言是一种在程序中用于检查特定条件是否满足的工具。一般用于验证开发者的假设&#xff0c;如果条件不成立&#xff0c;就会导致程序报…...

概念杂记--到底啥是啥?(数据库篇)

文章目录 1.聚集索引&#xff08;clustered index&#xff09;2.非聚集索引&#xff08;Non-clustered index&#xff09;3.聚集索引和非聚集索引区别&#xff1f;4.覆盖索引&#xff08;covering index&#xff09;5、复合索引 &#xff08;Composite Index&#xff09;6.索引…...

Ubuntu20.4 Mono C# gtk 编程习练笔记(四)

连续实时绘图 图看上去不是很清晰&#xff0c;KAZAM录屏AVI尺寸80MB&#xff0c; 转换成gif后10MB, 按CSDN对GIF要求&#xff0c;把它剪裁缩小压缩成了上面的GIF&#xff0c;图像质量大不如原屏AVI&#xff0c;但应该能说明原意&#xff1a;随机数据随时间绘制在 gtk 的 drawin…...

1 月 26日算法练习

文章目录 九宫幻方穿越雷区走迷宫 九宫幻方 小明最近在教邻居家的小朋友小学奥数&#xff0c;而最近正好讲述到了三阶幻方这个部分&#xff0c;三阶幻方指的是将1~9不重复的填入一个33的矩阵当中&#xff0c;使得每一行、每一列和每一条对角线的和都是相同的。 三阶幻方又被称…...

今日AI大热潮,明日智能风向标

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…...

03 SB实战 -微头条之首页门户模块(跳转某页面自动展示所有信息+根据hid查询文章全文并用乐观锁修改阅读量)

1.1 自动展示所有信息 需求描述: 进入新闻首页portal/findAllType, 自动返回所有栏目名称和id 接口描述 url地址&#xff1a;portal/findAllTypes 请求方式&#xff1a;get 请求参数&#xff1a;无 响应数据&#xff1a; 成功 {"code":"200","mes…...

Abaqus许可分析工具

在当今的知识产权保护和许可管理领域&#xff0c;一款高效、精准的许可分析工具对于企业来说至关重要。Abaqus许可分析工具凭借其强大的功能和卓越的性能&#xff0c;成为了企业优化知识产权许可管理的得力助手。 一、Abaqus许可分析工具的核心优势 1.全面性&#xff1a;Abaqus…...

【开发工具】从eclipse到idea的过度

背景 随着eclipse相比以前性能慢了不少&#xff0c;idea在开发工具领域越战越猛&#xff0c;市场份额也逐年增加&#xff0c;其体验得了软件工程师的热爱。 概要 本文只是做了一个简要的记录&#xff0c;简单描述下本人从eclipse到idea的过度的心态。 正文 在大厂都会研发自…...

【QT+QGIS跨平台编译】之十一:【libzip+Qt跨平台编译】(一套代码、一套框架,跨平台编译)

文章目录 一、libzip介绍二、文件下载三、文件分析四、pro文件五、编译实践一、libzip介绍 libzip是一个开源C库,用于读取,创建和修改zip文件。 libzip可以从数据缓冲区,文件或直接从其他zip归档文件直接复制的压缩数据中添加文件。在不关闭存档的情况下所做的更改可以还原…...

openlayers+vue实现缓冲区

文章目录 前言一、准备二、初始化地图1、创建一个地图容器2、引入必须的类库3、地图初始化4、给地图增加底图 三、创建缓冲区1、引入需要的工具类库2、绘制方法 四、完整代码总结 前言 缓冲区是地理空间目标的一种影响范围或服务范围,是对选中的一组或一类地图要素(点、线或面…...

(大众金融)SQL server面试题(3)-客户已用额度总和

今天&#xff0c;面试了一家公司&#xff0c;什么也不说先来三道面试题做做&#xff0c;第三题。 那么&#xff0c;我们就开始做题吧&#xff0c;谁叫我们是打工人呢。 题目是这样的&#xff1a; DEALER_INFO经销商授信协议号码经销商名称经销商证件号注册地址员工人数信息维…...

c语言笔记

1. c语言部分算法列举 1.1 找数 二分查找&#xff08;前提是数据必须有序&#xff09; 1.2 求极值 1.3 数组逆序 1.4 排序法&#xff08;***重点***&#xff09; 1.4.1 选择排序法 1.4.2 冒泡排序法 1.4.3 插入排序法 2. 字符型数组 2.1 使用格式 char s[10]; …...

6轴机器人运动正解-逆解控制【1】——三种控制位姿的方式

概览&#xff1a; 通过运动学正解控制机器人运动通过运动学逆解控制机器人运动一个简单的物体搬运&#xff08;沿轨迹运动&#xff09; 后续会陆续更新&#xff08;本例仅供学习交流用&#xff09; 一、6轴机器人 二、运动正解控制 通过修改各个轴的角度&#xff0c;实现末…...

c# Microsoft UI Automation

Microsoft UI Automation&#xff08;UIA&#xff09;是一种用于自动化Windows应用程序用户界面&#xff08;UI&#xff09;的框架。它允许开发人员编写自动化测试脚本、辅助技术应用程序和其他需要与应用程序交互的工具。以下是一些关于Microsoft UI Automation的重要信息&…...

C#-前后端分离连接mysql数据库封装接口

C#是世界上最好的语言 新建项目 如下图所示选择框红的项目 然后新建 文件夹 Common 并新建类文件 名字任意 文件内容如下 因为要连接的是mysql数据库 所以需要安装 MySql.Data.MySqlClient 依赖; using MySql.Data.MySqlClient; using System.Data;namespace WebApplication1.…...

yolov8 opencv dnn部署自己的模型

源码地址 本人使用的opencv c github代码,代码作者非本人 使用github源码结合自己导出的onnx模型推理自己的视频 推理条件 windows 10 Visual Studio 2019 Nvidia GeForce GTX 1070 opencv4.7.0 (opencv4.5.5在别的地方看到不支持yolov8的推理&#xff0c;所以只使用opencv…...

插槽(64-67)

文章目录 插槽1.插槽 - 默认插槽(组件内可以定制一处结构)2.插槽 - 后备内容&#xff08;默认值&#xff09;3.插槽 - 具名插槽(组件内可以定制多处结构)4.作用域插槽(插槽的一个传参语法) 插槽 插槽分类:默认插槽和具名插槽 1.插槽 - 默认插槽(组件内可以定制一处结构) 作用…...

C# LING查询语法学习,扩展方法的使用

class Program { #region 示例1&#xff1a;不使用LINQ查询数组 //static void Main(string[] args) //{ // int[] nums { 1, 7, 2, 6, 5, 4, 9, 13, 20 }; // List<int> list new List<int>(); // foreach (int item in nums) …...

自然语言推断:微调BERT

微调BERT 自然语言推断任务设计了一个基于注意力的结构。现在&#xff0c;我们通过微调BERT来重新审视这项任务。自然语言推断是一个序列级别的文本对分类问题&#xff0c;而微调BERT只需要一个额外的基于多层感知机的架构&#xff0c;如下图中所示。 本节将下载一个预训练好的…...

立创EDA学习:设计收尾工作

布线整理 ShiftM&#xff0c;关闭铺铜显示 调整结束后再使用快捷键”ShiftM“打开铺铜 过孔 在空白区域加上一些GND过孔&#xff0c;连接顶层与底层的铺铜。放置好”过孔“后&#xff0c;隐藏铺铜&#xff0c;观察刚才放置的过孔有没有妨碍到其他器件 调整铺铜 先打开铺铜区&…...

ShardingSphere之ShardingJDBC客户端分库分表上

目录 什么是ShardingSphere&#xff1f; 客户端分库分表与服务端分库分表 ShardingJDBC客户端分库分表 ShardingProxy服务端分库分表 ShardingSphere实现分库分表的核心概念 ShardingJDBC实战 什么是ShardingSphere&#xff1f; ShardingSphere是一款起源于当当网内部的应…...

rust for循环步长-1,反向逆序遍历

fn main() {for i in (0..3).rev().step_by(1) {print!("{}", i);} } // 打印结果&#xff1a;210Trait std::iter::Iterator fn rev(self) -> Rev< Self > where Self: Sized DoubleEndedIteratorfn step_by(self, step: usize) -> StepBy< Self &…...

编译与运行环境(C语言)

文章目录 前言编译环境编译链接 运行环境 前言 C语言代码的实现&#xff0c;存在两种不同的环境。 第一种是翻译环境&#xff0c;在这个环境中&#xff0c;源代码被转换为可执行的二进制指令。 翻译环境即我们日常使用编译器&#xff0c;将一个 " mission.c " 的文件…...

再谈Android View绘制流程

一&#xff0c;先思考何时开始绘制 笔者在这里提醒读者&#xff0c;Android的View是UI的高级抽象&#xff0c;我们平时使用的XML文件也好&#xff0c;本质是设计模式中的一种策略模式&#xff0c;其View可以理解为一种底层UI显示的Request。各种VIew的排布&#xff0c;来自于开…...

分布式定时任务系列8:XXL-job源码分析之远程调用

传送门 分布式定时任务系列1&#xff1a;XXL-job安装 分布式定时任务系列2&#xff1a;XXL-job使用 分布式定时任务系列3&#xff1a;任务执行引擎设计 分布式定时任务系列4&#xff1a;任务执行引擎设计续 分布式定时任务系列5&#xff1a;XXL-job中blockingQueue的应用 …...

python+Qt5 UOS 摄相头+麦克风测试,摄相头自动解析照片二维条码,麦克风解析音频文件

UI图片&#xff1a; 源代码&#xff1a; # -*- coding: utf-8 -*-# Form implementation generated from reading ui file CameraTestFrm.ui # # Created by: PyQt5 UI code generator 5.15.2 # # WARNING: Any manual changes made to this file will be lost when pyuic5 is…...

MongoDB日期存储与查询、@Query、嵌套字段查询实战总结

缘由 MongoDB数据库如下&#xff1a; 如上截图&#xff0c;使用MongoDB客户端工具DataGrip&#xff0c;在filter过滤框输入{ profiles.alias: 逆天子, profiles.channel: }&#xff0c;即可实现昵称和渠道多个嵌套字段过滤查询。 现有业务需求&#xff1a;用Java代码来查询…...

Windows版本Node.js常见问题及操作解决方式(小白入门必备)

npm i时ERROR:reason: certificate has expired问题 https://blog.csdn.net/m0_73360677/article/details/135774500 # 1.取消ssl验证&#xff1b;npm config set strict-ssl false#这个方法一般可以直接解决问题&#xff0c;如不能请尝试第二种方法# 2.更换npm镜像源&#x…...

09.Elasticsearch应用(九)

Elasticsearch应用&#xff08;九&#xff09; 1.搜索结果处理包括什么 排序分页高亮返回指定字段 2.排序 介绍 Elasticsearch支持对搜索结果排序&#xff0c;默认是根据相关度算分来排序 支持排序的字段 keyword数值地理坐标日期类型 排序语法 GET /[索引名称]/_sear…...

ROS2常用命令工具

ROS2常用命令工具 包管理工具ros2 pkg ros2 pkg create ros2 pkg create --build-type ament_python pkg_name rclpy std_msgs sensor_msgs –build-type : C或者C ament_cmake &#xff0c;Python ament_python pkg_name &#xff1a;创建功能包的名字 rclpy std_msgs sens…...

一起作做业网站/天天seo伪原创工具

bitsCN.comLinux下均在控制台下操作。导入数据库&#xff1a;前提&#xff1a;数据库和数据表要存在(已经被创建)(1)将数据表 test_user.sql 导入到test 数据库的test_user 表中[roottest ~]# mysql -uroot -p test < /www/web/test/test_user.sql(2) 将数据库 test.sql 导入…...

酷万网站建设/关键词竞价广告

亲测验证适用于5.7.10 1. 获得二进制文件 wget http://mirrors.sohu.com/mysql/MySQL-5.7/mysql-5.7.10-linux-glibc2.5-x86_64.tar.gz 2. 加压到 /usr/local/mysql 目录(或者解压到当前目录然后做软链接到/usr/local/mysql)mkdir /usr/local/mysqltar -xvf mysql-5.7.10-linu…...

biz后缀的网站/企业建站公司热线电话

CountDownLatch 是多线程控制的一种工具&#xff0c;它被称为 门阀、 计数器或者 闭锁。这个工具经常用来用来协调多个线程之间的同步&#xff0c;或者说起到线程之间的通信&#xff08;而不是用作互斥的作用&#xff09;。下面我们就来一起认识一下 CountDownLatch 认识 Coun…...

设计参考图哪个网站好/微信怎么推广找客源

http://www.cnblogs.com/whoislcj/p/5711001.html 前言&#xff1a; 上篇介绍了自定义控件的基本要求以及绘制的基本原理&#xff0c;本篇文章主要介绍如何给自定义控件自定义一些属性。本篇文章将继续以上篇文章自定义圆形百分比为例进行讲解。有关原理知识请参考Android自定…...

so域名网站/佛山疫情最新消息

系列文章目录 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 TODO:写完再整理 文章目录系列文章目录前言&#xff08;1&#xff09;EKF工作原理&#xff08;2&#xff09;话题数据接口&#xff08;3&#xff09;配置robot_pose_ekf.…...

永川做网站的公司/百度大数据平台

代码 关键字: javascript this用法小结this是JavaScript中功能最强大的关键字之一。不幸的是&#xff0c;如果你不知道它具体怎么工作&#xff0c;你将很难正确使用它。this是面向对象语言中的一个重要概念&#xff0c;在JAVA,C#等大型语言中&#xff0c;this固定指向运行时的当…...