“锟斤拷,烫烫烫,屯屯屯”的由来

server/2024/9/19 18:54:12/ 标签: c++, 调试, 乱码, 历史

在程序开发过程中,调试是不可或缺的一环。调试不仅可以帮助开发者发现错误,还能提供程序运行时的内部状态信息。然而,在调试过程中,开发者有时会遇到一些奇怪的字符。这些乱码通常是由内存状态的特殊标记,或者字符集不匹配导致的。在本文中,我们将探讨这些乱码的由来,以及它们在程序开发中的含义。

内存调试与特殊填充值

在Visual Studio(MSVC)和Clang等编译器中,为了帮助开发者发现和调试内存使用错误,编译器和运行时库会使用特殊的填充值(也称为幻数,Magic Numbers)来标记未初始化的内存、新分配的堆内存以及已经释放的内存。这些填充值有助于识别内存损坏和使用未初始化的变量等问题。

MSVC的内存填充值

在Microsoft Visual C++ (MSVC) 编译器中,Debug模式下会使用以下填充值来标识内存状态:

  1. 未初始化的栈内存:通常填充为 0xCC。在x86架构的汇编中,0xCC 对应的指令是 INT 3,它是一个软件中断指令,常用于调试断点。如果代码尝试执行这部分内存,程序会因为触发了断点而停止。

  2. 新分配的堆内存:常被填充为 0xCD。这个值在调试器中没有特定的指令对应,但它可以帮助开发者快速识别出使用了未初始化的堆内存。新分配的但还未提交的内存页通常也填充为 0xCD

  3. 已经释放的堆内存:通常填充为 0xDD。这样做是为了标记内存已经不再有效,如果代码试图访问释放的堆内存,这个填充值可以帮助开发者发现悬挂指针(dangling pointer)问题。为了方便记忆,可以理解成DeleteDelete(DD)。

在MSVC中,我们还可以通过更细致的配置来优化调试体验:

  • _CRTDBG_MAP_ALLOC:通过定义此宏,可以使得malloc、calloc等内存分配函数映射到调试版本,从而在调试输出中提供更详细的分配信息。
  • _CRTDBG_FILL_MEMORY:在调试版本中,可以设置此宏来控制自由内存块的填充模式和值,进一步定制化内存检查策略。
  • /RTC 编译选项:使用运行时错误检查选项,如/RTC1(默认)会检测未初始化的局部变量,而/RTCc会强制所有堆和栈变量初始化。

Clang的内存填充值

Clang编译器,也会使用特殊的填充值来帮助开发者识别内存错误。AddressSanitizer是一个快速的内存错误检测器,可以检测出包括使用后释放(use-after-free)、堆栈缓冲区溢出、堆缓冲区溢出、全局缓冲区溢出、使用前初始化(use-before-init)等多种内存错误。

当使用AddressSanitizer时,Clang会对内存进行特殊的处理:

  1. 堆内存:新分配的堆内存会被初始化为特定的模式,通常是一系列的0xAB字节。而一旦堆内存被释放,它会被填充为一系列的0xEF字节。这些值有助于识别使用后释放和堆溢出错误。可以记忆成:ABCDEF,用之前是AB,用之后是EF。

  2. 栈内存:未初始化的栈变量通常会被填充为一系列的0xAB字节。这有助于发现栈变量的使用前初始化错误。

  3. 全局变量:同样,全局或静态变量会被填充为特定的字节模式,以帮助识别未初始化的使用。

AddressSanitizer还会在分配的内存块周围插入"红区"(red zones),这是一些额外的非可访问区域,用以检测缓冲区溢出错误。

需要注意的是,这些填充值和行为是AddressSanitizer的特性,并不是Clang编译器在所有编译模式下的默认行为。在不使用AddressSanitizer的情况下,Clang编译器默认并不会自动对未初始化的内存进行填充。但是,如果开启了某些特定的调试或安全特性,Clang可能会有类似的行为。

GCC的情况

GCC(GNU Compiler Collection)本身并不像MSVC那样在Debug模式下自动填充未初始化的内存。然而,当使用GCC配合特定的内存错误检测工具,如Valgrind或GCC的Sanitizers(例如AddressSanitizer, MemorySanitizer)时,会有类似的行为。

AddressSanitizer(ASan)和MemorySanitizer(MSan)是用于快速检测各种常见的内存错误和未定义行为的工具。

  • AddressSanitizer(GCC和Clang均支持):它会在堆内存分配时使用特殊的填充值,并在释放后也会标记这些内存。新分配的堆内存通常填充为 0xAB 字节,释放后的堆内存填充为 0xEF 字节。AddressSanitizer还会在分配的内存块前后插入保护区,帮助检测堆溢出和使用后释放错误。

  • Valgrind:Valgrind是一个开源的软件工具,它提供了一系列的工具用于调试内存管理和线程错误,以及分析性能。Valgrind被广泛用于发现Linux和其他类Unix系统上C和C++程序中的内存管理错误,如内存泄露、不正确的内存分配和释放、使用未初始化的内存、数组越界、不正确的使用malloc/new和free/delete等。

简而言之,GCC并不会自动在Debug构建中填充栈内存。如果需要检测对未初始化栈内存的使用,可以使用工具如Valgrind或GCC的 -finit-local-zero 选项,后者会初始化所有局部变量为零,但这会导致性能下降,不建议在生产环境中使用。

总结来说,GCC自身并不指定特定的填充值来标记未初始化的内存或者释放后的内存,而是依赖于外部工具或编译器选项来帮助开发者发现内存相关的错误。

烫烫烫,屯屯屯”的由来

由于Visual Studio调试器默认使用的是多字节字符集(MBCS),在MBCS中0xCCCC对应中文字符“烫”,因此未初始化的栈内存显示为连串的“烫”。另一方面,新分配的堆内存会被初始化为0xCD,在MBCS中0xCDCD对应的是中文字符“屯”。

锟斤拷的由来

在Unicode中,当遇到无法表示的字符时,会使用一个特殊的占位符来表示,这个字符是U+FFFD REPLACEMENT CHARACTER。任何无法识别的字符都会被替换为这个字符,其UTF-8编码是0xEFBFBD。如果连续出现多次无法显示的字符,对应的编码序列就是连续的0xEFBFBD,在UTF-8编码下16进制表示为:

0xEF 0xBF 0xBD 0XEF 0xBF 0xBD

以上这段编码,如果放到GBK中进行解码的话,因为GBK中一个下汉字两个字节,那么
结果就是:
0xEF 0xBF , 0xBD 0XEF , 0xBF 0xBD
这个结果对应的字符就是:锟(0xEFBF),斤(0xBDEF),拷(0xBFBD)。
所以,以后再见到银斤拷,第一时间想到UTF-8和GBK的转换问题准没错。
可见,“锟斤拷”这样的乱码是由于新旧编码系统转换不匹配造成的。

在这里插入图片描述


http://www.ppmy.cn/server/51071.html

相关文章

计算机网络 —— 应用层(应用层概述及服务方式)

计算机网络 —— 应用层(应用层概述及服务方式) 应用层服务方式C/S(客户端-服务器(C/S)模型)基本概念特点B/S(Browser/Server)基本概念特点应用场景 p2p (对等网络&#…

c++学习 文件操作,模板

文件操作 #include<iostream> #include<string> #include<fstream> using namespace std; //文本操作 //程序运行时产生的数据都属于临时数据&#xff0c;程序一旦运行结束都会被释放 //通过文件可以数据持久化 //c中对文件操作包含头文件<fstream> /…

基于PaddleDetection的电路板瑕疵检测

文章目录 1. 数据集与框架介绍2. 任务详情3. Cascade R-CNN简介4. 数据分析各类别样本的数量真实框的宽高比真实框在原图的大小比例 5. 相关配置数据增强数据集路径和评估指标学习率和优化器配置预训练CascadeRCNN 的配置日志记录 6. 训练预测7. 参考链接 1. 数据集与框架介绍 …

猫头虎分享:IPython的使用技巧整理

&#x1f42f; 猫头虎分享&#xff1a;IPython的使用技巧整理 关于猫头虎 大家好&#xff0c;我是猫头虎&#xff0c;别名猫头虎博主&#xff0c;擅长的技术领域包括云原生、前端、后端、运维和AI。我的博客主要分享技术教程、bug解决思路、开发工具教程、前沿科技资讯、产品…

【字符串】常见算法题型及方法总结

什么是字符串&#xff1f; 字符串是若干字符组成的有限序列&#xff0c;可以理解为一个字符数组。在C中提供了一个string类&#xff0c;那我们可能会想vector<char>和string有什么区别呢。在含义和基本操作方面基本是没有区别的&#xff0c;但是string提供了更多相关接口…

C# —— 位运算符

简介 位运算符 主要是用于数值类型计算 运算方式: 将数值转换为二进制 在进行位运算 返回的是一个二进制转十进制的数值 如果二进制数 不够位置 则在前面补零 位与 & 规则: 连接两个数值进行位运算 将数值转换为二进制进行计算 对位运算 有零则零 int a 1; int b 5…

解决python从TD数据库取50w以上大量数据慢的问题

1.问题背景描述 python项目中的时序数据都存放在TD数据库中&#xff0c;数据是秒级存入的&#xff0c;当查询一周数据时将超过50w数据量&#xff0c;这是一次性获取全量数据到python程序很慢&#xff0c;全流程10秒以上&#xff0c;希望进行优化加速 2.排查 首先&#xff0c…

TCP如何保证数据传输的稳定性和可靠性

TCP&#xff08;传输控制协议&#xff09;通过多种机制确保数据传输的稳定性和可靠性。以下是TCP确保数据传输稳定性的几个关键机制&#xff0c;以及确认号和流量控制功能的关系&#xff1a; 三次握手&#xff08;Three-way Handshake&#xff09;&#xff1a; 建立连接时&…

你知道什么是微调吗?大模型为什么要微调?以及大模型微调的原理是什么?

“ 预训练(pretrain)微调(finetuning)&#xff0c;是目前主流的范式**”** 在学习大模型的过程中&#xff0c;怎么设计神经网络和怎么训练模型是一个重要又基础的操作。 但与之对应的微调也是一个非常重要的手段&#xff0c;这里就着重讲一下为什么要微调&#xff0c;其优点是…

【尚庭公寓SpringBoot + Vue 项目实战】租约管理(十四)

【尚庭公寓SpringBoot Vue 项目实战】租约管理&#xff08;十四&#xff09; 文章目录 【尚庭公寓SpringBoot Vue 项目实战】租约管理&#xff08;十四&#xff09;1、业务介绍2、逻辑介绍3、接口开发3.1、保存或更新租约信息3.2、根据条件分页查询租约列表3.3、根据ID查询租…

springboot 整合redis问题,缓存击穿,穿透,雪崩,分布式锁

boot整合redis 压力测试出现失败 解决方案 排除lettuce 使用jedis <!-- 引入redis --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><exclusions><exclus…

【0-1系列】从0-1快速了解搜索引擎是什么以及怎么用(上)

友情链接 社区开发版安装部署与使用教程社区版家族V2024.5版本更新说明 START>>1.快速了解搜索引擎 什么是搜索引擎数据库 搜索引擎数据库是一类专门用于数据内容搜索的NoSQL数据库&#xff0c;是非结构化大数据处理分析领域中重要的基础支撑软件。 伴随互联网、移动…

网络安全基础漏洞复习

一.sql注入 Mysql自带了Information_schema这个数据库&#xff0c; 5.0以下是没有的 布尔盲注 时间盲注sleep 报错注入 堆叠注入&#xff08;就是一下使用了两个SQL语句只不过使用 ; 来把他们分隔开&#xff09; 报错常用函数&#xff1a;extractvalue updatexml exp 基于g…

不同类型的Shell脚本

大家好&#xff0c;我是G探险者。 在linux里面执行某个shell脚本的时候&#xff0c;发现执行不了&#xff0c;说什么不兼容&#xff0c;研究了一下发现shell脚本也有这么多的类型&#xff0c;下面就简单聊聊。 简介 Shell脚本是一种用于自动化任务的强大工具&#xff0c;广泛…

开发一个python工具,pdf转图片,并且截成单个图片,然后修整没用的白边及循环遍历文件夹全量压缩图片

今天推荐一键款本人开发的pdf转单张图片并截取没有用的白边工具 一、开发背景&#xff1a; 业务需要将一个pdf文件展示在前端显示&#xff0c;但是基于各种原因&#xff0c;放弃了h5使用插件展示 原因有多个&#xff0c;文件资源太大加载太慢、pdf展示兼容性问题、pdf展示效果…

3D模型在电商行业的应用有哪些?

3D模型在电商行业的应用广泛且多样化&#xff0c;以下是几个主要的应用领域&#xff1a; 1、商品展示&#xff1a; 3D立体展示技术能够利用商品的3D模型进行全方位的展示&#xff0c;支持720旋转和任意缩放&#xff0c;使得消费者能够更直观地了解产品的外观、结构和特点。这…

Spring Boot常用注解

EnableAutoConfiguration: 作用自动扫描并添加jar包依赖 SpringBootApplication: 原理是一个组合注解&#xff0c;相当于EnableAutoConfiguration和ComponentScan RestController: 用于标注控制层组件(如struts中的action)&#xff0c;包含Controller和ResponseBody Reposit…

排序(2)【选择排序】【快速排序】

一.选择排序 选择排序就是选择一个数组的最大的数字或者最小的数字&#xff0c;放在一整个数组的最后或者开头的位置。 1.选择排序的实现 我们可以对选择排序进行一些加强&#xff0c;普通的选择排序是选择最小的数&#xff0c;然后进行交换。这个加强之后就是我们既要选择出…

支付宝H5支付

业务场景&#xff1a;需要再手机端H5使用支付宝的支付&#xff01; 第一步&#xff1a; 开通支付宝商户,支付宝开放平台地址放在这里了。 第二步&#xff1a; 创建应用开通支付产品功能&#xff1a; 创建应用就不单一切图了&#xff01;登录账户-管理中心就能看到-选择网页…

微信小程序知识点概况

1. 基本概念 微信小程序&#xff1a;是一种新的开放能力&#xff0c;开发者可以快速地开发一个小程序。小程序能够在微信内被便捷地获取和传播&#xff0c;同时具有出色的使用体验。 特点&#xff1a; 无需安装&#xff1a;用户通过扫描二维码或搜索即可使用。触手可及&…