C之(15)cppcheck使用介绍

C之(15)cppcheck使用介绍


Author: Once Day Date: 2025年3月23日

一位热衷于Linux学习和开发的菜鸟,试图谱写一场冒险之旅,也许终点只是一场白日梦…

漫漫长路,有人对你微笑过嘛…

全系列文章可查看专栏: Linux实践记录_Once_day的博客-CSDN博客

参考文章:

  • CppCheck静态代码检查工具教程【Windows和Linux端】-CSDN博客
  • cppcheck的安装及基本使用_cppcheck这个操作只对当前安装的产品有效-CSDN博客
  • Cppcheck - A tool for static C/C++ code analysis

文章目录

  • C之(15)cppcheck使用介绍
        • 1. cppcheck介绍
          • 1.1 概述
          • 1.2 检查结果
          • 1.3 检查规则和过滤
        • 2. 基本使用方法
        • 3. 参数介绍
        • 4. gitlab-ci集成

1. cppcheck介绍
1.1 概述

Cppcheck是一款静态代码分析工具,专门用于检查C/C++代码中潜在的错误和漏洞。它由瑞典程序员Daniel Marjamäki在2007年开发,旨在帮助开发者提高代码质量,减少bug。

Cppcheck的诞生源于Daniel在工作中遇到的一些棘手的编程问题。他发现,许多C/C++项目中存在许多常见的编码错误,如内存泄漏、未初始化变量、数组越界等,这些问题不易被发现,但却可能导致程序崩溃或产生安全隐患。为了解决这一痛点,Daniel利用业余时间开发了Cppcheck。

最初,Cppcheck只是一个简单的命令行工具,功能较为单一。但随着时间推移,在全球开源社区的共同努力下,Cppcheck不断完善,功能日益强大。目前,它已经成为了C/C++开发者必不可少的代码检查工具之一,被广泛应用于各种项目中,从小型单机程序到大型服务器软件,涵盖领域十分广泛。

Cppcheck的核心价值在于提升代码质量,减少潜在错误。它通过静态分析代码,能够精确地定位出各种问题,如unused functions、unexpectedsign、uninitialized variables等,并给出改进建议。同时,Cppcheck也提供了丰富的自定义规则,用户可以根据自己的需求进行个性化设置。

使用Cppcheck非常简单,通常只需一行命令即可。例如,要检查当前目录下的所有.cpp文件,只需执行:

cppcheck --enable=all .

Cppcheck就会自动分析每个文件,输出检查结果,并指出问题所在的行号和具体原因。用户可以根据这些信息快速定位并修复代码缺陷,大大提高开发效率。

除了命令行,Cppcheck还支持多种集成方式,可以与Visual Studio、Eclipse等流行IDE无缝对接,实现图形化操作。同时,Cppcheck也提供了Python绑定,方便进行二次开发和功能扩展。

1.2 检查结果

Cppcheck的检查结果主要分为以下几类:

(1)Error(错误):这是最严重的问题,意味着代码中存在明显的缺陷或漏洞,可能导致程序崩溃、数据损坏等危险后果。

  • 内存泄漏:动态分配的内存没有被正确释放,长期积累可能耗尽系统资源。
  • 悬空指针:指针指向了已经释放的内存区域,再次使用可能引发无法预料的错误。
  • 除零错误:将一个数除以0会导致程序异常退出。
  • 数组越界:访问了数组边界之外的内存,可能覆盖其他关键数据。

(2)Warning(警告):Warning通常指出了代码中的一些不规范或可疑的写法,虽然不会直接导致错误,但可能隐藏着潜在的bug。开发者应该仔细检查这些警告,采取防御性编程策略,以提高代码的健壮性。

  • 未初始化变量:变量在使用前没有赋予初值,其内容是不可预知的。
  • 死代码:一些永远不会被执行到的代码片段,通常暗示存在BUG。
  • 忽略返回值:忽略了某些函数的返回值,可能错过了重要的错误信息。

(3)Style(编码风格):Style指出了代码的一些格式问题,虽然不影响程序的功能,但影响可读性、可维护性。

  • 未使用的函数:定义了一些函数,但在代码中并未被调用,建议删除。
  • 多余的代码:一些无用的变量定义、赋值、条件判断等,应该剔除。
  • 缩进不规范:没有遵循统一的缩进标准,使代码显得混乱。

(4)Portability(移植性):Portability提示了代码在跨平台、跨编译器时可能遇到的兼容性问题。

  • 大小端问题:不同CPU架构下,多字节数据的存储顺序可能相反。
  • 数据类型长度:不同平台下,int、long等类型的字节长度可能不一致。
  • 特定编译器的语法:使用了某些编译器特有的语法,在其他编译器下可能无法通过编译。

(5)Performance(性能):Performance给出了一些优化代码性能的建议,帮助开发者写出更高效的程序。

  • 循环展开:建议将一些小循环展开,以减少迭代次数。
  • 避免不必要的临时对象:在循环内部创建大量临时对象,建议放在循环外处理。

(6)Information(信息):Information是一些有趣的提示信息,不太重要,可以忽略。

  • 幻数:代码中用到了一些未命名的神秘数字,难以猜测其含义。
  • 文档格式:doxygen等文档注释的格式不标准。
1.3 检查规则和过滤

Cppcheck提供了丰富的检查规则,可以从多个维度审视代码质量。

检查规则描述
自动变量检查Cppcheck会检查自动变量的使用是否规范,如是否在使用前初始化、是否存在死代码等。这可以避免很多潜在的bug。
数组边界检查数组越界是C/C++中常见的错误之一。Cppcheck可以准确定位出数组访问是否越界,提醒开发者注意边界条件的处理。
类检查Cppcheck对类的使用提供了全面的检查,如构造函数、析构函数的正确性,虚函数的覆盖情况,operator=的实现等,帮助写出更健壮的类。
过期废弃函数检查某些老旧的C/C++函数已经被标记为过期或废弃,不建议继续使用。Cppcheck可以自动识别这些函数,建议开发者使用新的替代品。
异常的内存使用和释放Cppcheck会严格检查内存分配和释放的匹配情况,及时发现可能导致内存泄漏或非法访问的异常操作。
内存泄漏检测借助Cppcheck,可以方便地定位内存泄漏发生的位置。Cppcheck主要通过分析指针的引用情况,判断动态分配的内存是否被正确释放。
系统资源管理对于文件句柄、互斥锁等系统资源,Cppcheck也提供了有效的检测,确保它们被正确创建、使用和释放,不会长期占用。
STL使用检查Cppcheck内置了常见STL容器和算法的使用规则,可以发现一些错误的使用方式,如迭代器失效、算法前置条件不满足等。
代码格式与性能除了纠正错误,Cppcheck还可以检查代码的格式规范性,提示一些可能影响性能的写法,如复杂度过高的函数、不必要的拷贝等。

尽管Cppcheck可以发现很多问题,但有时候我们可能希望忽略某些特定类型的警告,这时就可以使用--suppress选项进行过滤。

例如,使用下面的命令可以屏蔽所有的shadowVariable警告:

cppcheck --suppress=shadowVariable test.cpp

如果要屏蔽多个警告,可以用逗号分隔:

cppcheck --suppress=shadowVariable,unusedFunction test.cpp

除了按警告类型过滤,Cppcheck还支持更精细的过滤条件,如按文件、行号等。

2. 基本使用方法

在Ubuntu系统上安装和使用Cppcheck非常方便,下面我们就一步步来看看具体的操作过程。

打开终端,执行以下命令安装Cppcheck:

sudo apt-get update
sudo apt-get install cppcheck

等待安装完成后,可以通过–version选项检查安装是否成功:

cppcheck --version

如果显示了Cppcheck的版本号,说明安装成功。

要检查一个C/C++源文件,只需在终端中执行:

cppcheck test.cpp

Cppcheck就会自动分析test.cpp中的代码,并输出检查结果。

如果要检查多个文件,可以直接将它们作为参数传给Cppcheck:

cppcheck test1.cpp test2.cpp test3.cpp

要检查一个目录下的所有源文件,可以使用通配符:

cppcheck src/*.cpp

上述命令会检查src目录下的所有.cpp文件。

默认情况下,Cppcheck只会执行一些基本的检查。如果要启用所有检查,可以加上--enable=all选项:

cppcheck --enable=all test.cpp

这会启用所有的警告和建议,可以更全面地发现潜在问题。

下面我们用一个具体的例子来演示Cppcheck的使用。假设我们有以下一个简单的C++程序(test.cpp):

#include <iostream>
using namespace std;int main() {int* p = new int[10];p[10] = 1;  // 数组越界delete[] p;int a;cout << a << endl;  // 使用未初始化的变量return 0;
}

这个程序有两个明显的错误:数组越界和使用未初始化的变量。下面我们用Cppcheck来检查它:

cppcheck --enable=all test.cpp

Cppcheck会输出类似以下的结果:

Checking test.cpp ...
test.cpp:1:0: information: Include file: <iostream> not found. Please note: Cppcheck does not need standard library headers to get proper results. [missingIncludeSystem]
#include <iostream>
^
test.cpp:6:6: error: Array 'p[10]' accessed at index 10, which is out of bounds. [arrayIndexOutOfBounds]p[10] = 1;  // 数组越界^
test.cpp:10:13: error: Uninitialized variable: a [uninitvar]cout << a << endl;  // 使用未初始化的变量^
test.cpp:9:9: style: Variable 'a' is not assigned a value. [unassignedVariable]int a;^
nofile:0:0: information: Active checkers: 161/592 (use --checkers-report=<filename> to see details) [checkersReport]

可以看到,Cppcheck准确地发现了这两个错误,并指出了对应的代码行。我们可以据此快速定位和修复这些问题。

3. 参数介绍

Cppcheck的基本语法格式为:

cppcheck [OPTIONS] [files or paths]

如果输入参数是目录,那么目录下面的*.cpp, *.cxx, *.cc, *.c++, *.c, *.ipp,*.ixx, *.tpp, *.txx等文件会被依次递归的检查。

参数描述
–addon=执行插件,如 misra 等。如需额外选项需提供json配置文件
–addon-python=指定Python解释器路径,用于插件,优先级高于json配置
--cppcheck-build-dir=<dir>设置 Cppcheck 的工作目录,利于增量分析和全局分析
–check-config只检查 Cppcheck 配置,不作代码分析
--check-level=<level>配置检查深度,可选 normal (默认)、exhaustive
–check-library显示库文件信息不完整时的提示消息
--checkers-report=<file>将所有已启用的检查器信息写入指定文件
--clang=<path>试验性质地使用 Clang 分析器作为代码解析前端
--config-exclude=<dir>设置预处理配置检查的排除路径前缀
--config-excludes-file=<file>从文件中读取配置检查的排除路径前缀
--disable=<id>关闭指定的检查类型,如missingInclude
–dump以 xml 格式输出每个翻译单元的 AST、符号表等调试信息
-D定义预处理宏,可指定编译配置
-E输出预处理结果到标准输出,不做代码分析
–enable=启用额外检查,如 all、warning、style、performance、portability、information 等
–error-exitcode=发现错误时返回值为 n 而不是默认的0
–errorlist将所有错误消息以XML格式打印出来。
–exitcode-suppressions显示错误消息,但是不会造成退出返回值(–error-exitcode)为非0
--file-filter=<str>只分析文件名匹配 <str> 的文件,可多次使用
--file-list=<file>从文件中读取待分析的源文件列表
-f, --force强制检查所有编译配置,最后一次使用的 --max-configs 有效
–fsigned-char将 char 视为 signed char
–funsigned-char将 char 视为 unsigned char
–help, -h显示帮助信息
-I头文件搜索路径,相对路径无需设置
--include=<file>在被检查文件之前强制包含某文件
--includes-file=<file>从文件中读取包含路径
-i排除某个源文件或目录不做检查
–inconclusive允许 Cppcheck 输出不确定的分析结果
–inline-suppr允许使用行内抑制注释
-j并行检查的线程数
-l <load>设置负载阈值,控制启动新线程的时机
--language=<language>强制将所有文件作为指定语言(c、c++)来分析
–library=加载包含类型、函数信息的库文件。用于理解代码
–max-configs=单文件最大检查的编译配置数,默认12,和 -f 参数配合使用
–max-ctu-depth=N全局分析的最大迭代深度,默认为2
--output-file=<file>将结果输出到文件而不是标准错误流
–platform=指定特定平台的数据类型大小,可选如 unix32、win64 等
--plist-output=<path>在指定目录下生成 Clang-plist 格式的输出文件
–project=分析工程文件,支持.sln、.vcxproj、compile_commands.json 等
--project-configuration=<config>在分析 .sln 或 .vcxproj 时指定欲分析的项目配置
-q, --quiet不显示进度,但不影响详细信息的显示
-rp, --relative-paths=输出结果使用相对路径
–report-progress在分析每个文件时报告进度(仅单线程)
–rule=匹配正则表达式规则的警告信息
--rule-file=<file>使用指定的规则文件
--showtime=<mode>输出不同粒度的性能分析数据
–std=设置标准,如 c99、c++11
–suppress=抑制匹配 格式的警告
--suppressions-list=<file>从文件读取警告抑制列表
--suppress-xml=<file>从xml文件读取警告抑制列表
–template=‘’定制输出格式
--template-location='<text>'定制错误信息的位置输出格式
-U取消预定义的宏,用于隐藏特定的 #ifdef 代码分支
-v, --verbose输出更详细的错误信息
-version显示 Cppcheck 版本号
–xml将结果以 XML 格式输出到错误流(stderr)

Cppcheck 还有一些其他参数未在表格中列出,具体可参考完整的命令行帮助信息。

4. gitlab-ci集成

下面展示一种将Cppcheck集成到gitlab ci流水线的方法,GitHub和Gitee都可以以此作为参考:

首先需要一个运行Cppcheck的脚本run_cppcheck.sh,在该脚本里指定Cppcheck运行参数和处理结果:

# 当前目录路径
export SOURCE_DIR=${SOURCE_DIR:-$(pwd)}# 定义参数
# 除了 missingInclude 其他都是默认开启的
CPP_ARGS="--enable=style,performance,portability,unusedFunction,information"
CPP_ARGS="$CPP_ARGS --disable=missingInclude"
# 忽略不确定的检查
CPP_ARGS="$CPP_ARGS --inconclusive"
# 强制检查所有文件
CPP_ARGS="$CPP_ARGS --force"
# 忽略内联的警告
CPP_ARGS="$CPP_ARGS --inline-suppr"
CPP_ARGS="$CPP_ARGS --library=posix"
# 指定C和C++的标准
CPP_ARGS="$CPP_ARGS --std=c++11 --std=c11 --fsigned-char"
# 发现错误时 exit-code = 1
CPP_ARGS="$CPP_ARGS --error-exitcode=1"# set -x
# 对代码进行静态检查
cppcheck $CPP_ARGS $SOURCE_DIR/anmk/
if [ $? -ne 0 ]; thenecho "Cppcheck failed"exit 1
fiecho "Cppcheck success"
exit 0

首先,脚本设置了 SOURCE_DIR 环境变量,表示源代码的根目录路径,默认为当前目录。

接下来,通过 CPP_ARGS 变量定义了传递给 Cppcheck 的各种参数:

  • --enable: 启用额外的检查,如编码风格、性能、可移植性、未使用函数、信息提示等。
  • --disable: 禁用 missingInclude 检查。
  • --inconclusive: 允许 Cppcheck 报告不确定的结果。
  • --force: 强制检查所有文件和编译配置。
  • --inline-suppr: 支持使用行内抑制注释。
  • --library: 使用 POSIX 库进行分析。
  • --std: 指定 C 和 C++ 的语言标准。
  • --error-exitcode: 发现错误时返回非零的退出码。

然后,脚本运行 Cppcheck 命令,将 SOURCE_DIR/anmk/ 目录下的代码作为分析对象,应用之前定义的所有参数。

通过检查 Cppcheck 的返回值,如果不为0,说明存在静态分析问题,脚本输出错误信息并以非零状态码退出;反之则代表检查通过,脚本输出成功信息并正常退出。

.gitlab-ci.yml配置如下:

# 本地构建阶段 - 代码静态检查, 存在静态检查问题则失败
develop-static-check:stage: local-buildtags:- anmk-buildneeds: []script:- echo "Check ANMK Project - Develop Version - Static"- ./run_cppcheck.sh- echo "Check finished"

定义了一个名为 develop-static-check 的job,用于对开发版本的代码进行静态检查。

该job在 local-build 阶段运行,使用 anmk-build 的标签来选择合适的runner。

needs: [] 表示该job不依赖于其他任务,可以独立运行。

script 部分定义了该job的运行脚本:

  • 输出提示信息,表示开始对开发版本的ANMK项目代码进行静态检查。
  • 调用 run_cppcheck.sh 脚本执行实际的静态分析过程。
  • 输出提示信息,表示静态检查已完成。

通过这样的集成,每次提交或合并请求时,GitLab 都会自动触发 develop-static-check job,对代码进行 Cppcheck 静态分析。如果发现问题,流水线会失败并及时反馈,促使开发者尽快修复。

这种自动化的静态代码检查可以帮助提早发现代码缺陷,提高代码质量,减少后续的调试和维护成本。







Alt

Once Day

也信美人终作土,不堪幽梦太匆匆......

如果这篇文章为您带来了帮助或启发,不妨点个赞👍和关注,再加上一个小小的收藏⭐!

(。◕‿◕。)感谢您的阅读与支持~~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/38619.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Ant Design Vue Select 选择器 全选 功能

Vue.js的组件库Ant Design Vue Select 选择器没有全选功能&#xff0c;如下图所示&#xff1a; 在项目中&#xff0c;我们自己实现了全选和清空功能&#xff0c;如下所示&#xff1a; 代码如下所示&#xff1a; <!--* 参数配置 - 风力发电 - 曲线图 * 猴王软件学院 - 大强 …

CaiT (Class-Attention in Image Transformers):深度图像Transformer的创新之路

CaiT (Class-Attention in Image Transformers)&#xff1a;深度图像Transformer的创新之路 近年来&#xff0c;Transformers 模型在自然语言处理领域的成功逐渐扩展到了计算机视觉领域&#xff0c;尤其是图像分类任务中&#xff0c;Vision Transformer (ViT) 的提出打破了卷积…

Qt之MVC架构MVD

什么是MVC架构&#xff1a; MVC模式&#xff08;Model–view–controller&#xff09;是软件工程中的一种软件架构模式&#xff0c;把软件系统分为三个基本部分&#xff1a;模型&#xff08;Model&#xff09;、视图&#xff08;View&#xff09;和控制器&#xff08;Controll…

数组,指针 易混题解析(二)

目录 一.基础 1. 2. 二.中等 1. 坑 2. 3.指针1到底加什么 三.偏难 1.&#xff08;小端 x86&#xff09; 2.通过数组指针进行偏移的时候怎么偏移 3. 大BOSS &#xff08;1&#xff09;**cpp &#xff08;2&#xff09;*-- * cpp 3 &#xff08;3&#xff09;*c…

数据建模流程: 概念模型>>逻辑模型>>物理模型

数据建模流程 概念模型 概念模型是一种高层次的数据模型&#xff0c;用于描述系统中的关键业务概念及其之间的关系。它主要关注业务需求和数据需求&#xff0c;而不涉及具体的技术实现细节。概念模型通常用于在项目初期帮助业务人员和技术人员达成共识&#xff0c;确保对业务需…

spring-security原理与应用系列:建造者

目录 1.构建过程 AbstractSecurityBuilder AbstractConfiguredSecurityBuilder WebSecurity 2.建造者类图 SecurityBuilder ​​​​​​​AbstractSecurityBuilder ​​​​​​​AbstractConfiguredSecurityBuilder ​​​​​​​WebSecurity 3.小结 紧接上一篇文…

结合代码理解Spring AOP的概念(切面、切入点、连接点等)

前情回顾 对AOP的理解 我这篇文章介绍了为什么要有AOP&#xff08;AOP解决了什么问题&#xff09;以及如何实现AOP。但在实现AOP的时候&#xff0c;并未探讨AOP相关概念&#xff0c;例如&#xff1a;切面、切入点、连接点等。因此&#xff0c;本篇文章希望结合代码去理解Spring…

【AI大模型】搭建本地大模型GPT-NeoX:详细步骤及常见问题处理

搭建本地大模型GPT-NeoX:详细步骤及常见问题处理 GPT-NeoX是一个开源的大型语言模型框架,由EleutherAI开发,可用于训练和部署类似GPT-3的大型语言模型。本指南将详细介绍如何在本地环境中搭建GPT-NeoX,并解决过程中可能遇到的常见问题。 1. 系统要求 1.1 硬件要求 1.2 软…

Copilot提示词库用法:调整自己想要的,记住常用的,分享该共用的

不论你是 Microsoft 365 Copilot 的新用户还是熟练运用的老鸟&#xff0c;不论你是使用copilot chat&#xff0c;还是在office365中使用copilot&#xff0c;copilot提示词库都将帮助你充分使用copilot这一划时代的产品。它不仅可以帮助你记住日常工作中常用的prompt提示词&…

Spring:AOP

一、AOP概念的引入 为了更好地介绍AOP&#xff0c;我们以登录作为示例。 首先&#xff0c;我们先来看一下登录的原理&#xff1a; 如图所示&#xff0c;这是一个基本的登录原理图&#xff0c;但是如果我们想要在这个登录过程上再添加一些新的功能&#xff0c;比如权限校验&am…

Ubuntu实时读取音乐软件的音频流

文章目录 一. 前言二. 开发环境三. 具体操作四. 实际效果 一. 前言 起因是这样的&#xff0c;我需要在Ubuntu中&#xff0c;实时读取正在播放音乐的音频流&#xff0c;然后对音频进行相关的处理。本来打算使用的PipewireHelvum的方式实现&#xff0c;好处是可以直接利用Helvum…

CUDA 学习(4)——CUDA 编程模型

CPU 和 GPU 由于结构的不同&#xff0c;具有不同的特点&#xff1a; CPU&#xff1a;擅长流程控制和逻辑处理&#xff0c;不规则数据结构&#xff0c;不可预测存储结构&#xff0c;单线程程序&#xff0c;分支密集型算法GPU&#xff1a;擅长数据并行计算&#xff0c;规则数据结…

前端会话控制技术:cookie/session/token

目录 前端中的 Cookie、Session 和 Token&#xff1a;详解与应用1. Cookie1.1 什么是 Cookie&#xff1f;1.2 Cookie 的工作原理1.3 Cookie 的特点1.4 Cookie 的用途1.5 Cookie 的安全性 2. Session2.1 什么是 Session&#xff1f;2.2 Session 的工作原理2.3 Session 的特点2.4…

MATLAB实现基于“蚁群算法”的AMR路径规划

目录 1 问题描述 2 算法理论 3 求解步骤 4 运行结果 5 代码部分 1 问题描述 移动机器人路径规划是机器人学的一个重要研究领域。它要求机器人依据某个或某些优化原则 (如最小能量消耗&#xff0c;最短行走路线&#xff0c;最短行走时间等)&#xff0c;在其工作空间中找到一…

Shopify Checkout UI Extensions

结账界面的UI扩展允许应用开发者构建自定义功能&#xff0c;商家可以在结账流程的定义点安装&#xff0c;包括产品信息、运输、支付、订单摘要和Shop Pay。 Shopify官方在去年2024年使用结账扩展取代了checkout.liquid&#xff0c;并将于2025年8月28日彻底停用checkout.liquid…

电阻的阻值识别

电阻买回来是有偏差的&#xff0c;不同的电阻种类&#xff0c;它的偏差大小会不一样&#xff0c;偏差越小的肯定越贵 主要看要求的精度要求是否越高 色环电阻或者说插件电阻 用来读数的几个色环它是比较靠近的&#xff0c;精度的色环跟用来读数的几个色环的间距会大一点点。 间…

quartz.net条件执行

quartz.net条件执行 在使用Quartz.NET时&#xff0c;你可能需要基于某些条件来决定是否执行一个任务。Quartz.NET本身并不直接支持基于条件执行任务的功能&#xff0c;但你可以通过一些策略来实现这一需求。下面是一些方法来实现基于条件的任务执行&#xff1a; 1. 使用触发器…

计算机操作系统(四) 操作系统的结构与系统调用

计算机操作系统&#xff08;四&#xff09; 操作系统的结构与系统调用 前言一、操作系统的结构1.1 简单结构1.2 模块化结构1.3 分层化结构1.4 微内核结构1.5 外核结构 二、系统调用1.1 系统调用的基本概念1.2 系统调用的类型 总结&#xff08;核心概念速记&#xff09;&#xf…

NSSCTF(MISC)——[SUCTF 2018 招新赛]single-dog

相应的做题地址&#xff1a;https://www.nssctf.cn/problem/2324 分离图片 在1.txt中得到一段颜文字 http://www.hiencode.com/aaencode.html 解密得到flag

低功耗蓝牙(BLE)方案设计实战指南

一、BLE方案设计工具链 1. 硬件选型与开发平台 TI平台&#xff1a;CC2540/CC2541芯片&#xff0c;使用SmartRF Flash Programmer烧录Nordic平台&#xff1a;nRF51822芯片&#xff0c;使用nRFgo Studio管理协议栈常用调试工具&#xff1a;TI CC Debugger、J-Link&#xff08;SW…