在Xcode 7上直接使用Address Sanitizer

AddressSanitizer原理解析 AddressSanitizer的原理解析 阅读详情
在WWDC 2015上,除了Swift 2.0外,还有一个令人激动的消息:可以直接在Xcode 7上使用Clang的地址消毒剂(Address Sanitizer)了。这篇文章中我们将详细讨论下这个功能,比如它是怎样工作的,以及使用的方法。这是Konstantin Gonikman提议的话题。

C语言中一种异常危险的情况

从很多方面来看,C语言都是一种伟大的编程语言。事实上,发明至今已逾40年,它仍然保持着强劲的势头。这足以说明它的伟大。这不是我学的第一门(也不是第二门)编程语言,但正是它,使我第一次真正揭开了计算机运行机制的神秘面纱。而且,它是我至今仍在使用的唯一语言。

然而,C也是一门非常危险的编程语言,代码世界中的许多痛苦由它而生。它造成了许多怪异的bug,这些bug其他的编程语言根本无法表述。

内存安全是一个主要的问题。C语言中根本没有内存安全可言。像下面的代码,会被正常的编译,而且可能正常运行:

1
2
char *ptr = malloc(5);
ptr[12] = 0;

这段代码只申请了5字节的数组空间,却通过指针写入数据到第13字节上。在这个地址上,隐藏的数据损坏可能发生,也可能平安无事(比如在Apple平台上,malloc函数总是最少分配16个字节,即使你申请少于16字节的空间,因此这段代码在Apple平台上运行正常,但不要依赖系统的这个特性)。这段错误代码可能危害不大,也可能后患无穷。

更“聪明”的语言跟踪数组的大小,在操作的时候会验证下标的有效性。同样的Java代码,会比较可靠地抛出异常。有了异常机制,调试这些“神奇”问题就容易的多了。例如,一个变量应该为4,但实际上它的值为5,我们就知道某段修改该变量值的代码出了问题(这样至少我们会集中注意力到程序调试上,而不会盯着编译器,因为它一般不会出错)。但是使用C语言,我们根本无法做出假设,bug有可能是某段代码“故意”修改变量值造成的,也可能是某段代码使用了“坏指针”无意中修改了变量值。

整个产业已经开始着手解决这个问题。例如,Clang的静态代码分析,可以从代码中查找特定类型的内存安全问题。如Valgrind之类的程序可以在运行时检测到不安全的内存访问。

Address Sanitizer是另外一种解决方案。它使用了一种新的方法,有利有弊。但仍不失为一个查找代码问题的有力工具。

内存访问验证

许多这类工具在运行时验证内存访问的有效性,从而查找到问题。理论依据是:访问内存时,通过比较访问的内存和程序实际分配的内存,验证内存访问的有效性,从而在bug发生时就检测到它们,而不会等到副作用产生时才有所察觉。

理想情况下,每个指针都会包含数据大小和指向内存的位置信息,因此可针对这些验证每次的内存访问。为何C编译器在设计之初没有加入验证的特性,还没有具体的原因。但附加在指针上的元数据会使程序无法兼容标准C编译器编译的代码。这就意味着无法简单使用系统库,必然严重限制了使用该体系检测代码。

Valgrind解决以上问题的方案是:在模拟器上运行整个程序。这样,就可以直接运行标准C编译器生成的二进制文件,而不需要做任何额外的修改。然后在程序运行的时候进行分析,检查程序处理的每一块内存。这样的方式可以使它高效运行所有程序,包括系统的库,而不做任何修改。这样做的代价是速度变得很慢,因此在一些效率要求高的程序中不实用。另外,这种方式需要深度了解某个平台系统调用的含义,

只有这样才能合适地追踪内存改变状态。因而必然需要针对特定宿主系统的深度整合。多年间,Valgrind对Mac的支持无明确计划。截止本文发布之时,它还不支持Mac 10.10。

保护性内存分配得益于CPU内置的内存检查工具。它取代了标准的malloc函数。使用时,每个分配内存结尾的后面会被标记为不可读写。当程序尝试访问后面的内存,会出错。这样的做法有一个弊端:硬件的内存保护精确度不够。内存只能在内存页尺度上被标记为可读或不可读,而在现代操作系统中,内存页至少有4kB空间。这意味着每次内存分配至少都需要占用8kB内存:一页内存用来存储数据,另外一页用来限制越界的内存访问。即使只申请几字节的内存,也需要这样做。另外,这样的做法也导致小规模的越界不会被检测到。为了储存针对标准malloc的内存的保护,需要分配内存到16字节的范围内,因此,若分配的内存大小不是16字节的整数倍,余出的几个字节将不受保护。

内存消毒剂机制尝试在更小的粒度上处理内存受限。在本质上,这样的内存分配保护机制较慢,但却更实用。

追踪受限内存

既然不能使用硬件层面的内存保护,就必须使用软件的手段来实现。因为通过指针无法传递额外数据,跟踪内存必须通过某种“全局表”来完成。这个表需要能被快速的读取和修改。

内存消毒剂使用了一种简单但是很巧妙的方法:它在进程的内存空间上保存了一个固定的区域,叫做“影子内存区”。用内存消毒剂的术语来说,一个被标记为受限的内存被称作“中毒”内存。“影子内存区”会记录哪些内存字节是中毒的。通过一个简单的公式,可以将进程中的内存空间映射到“影子内存区”中,即:每8字节的正常内存块映射到一个字节的影子内存上。在影子内存上,会跟踪这8字节的“中毒状态”。

每8字节的内存映射8位(1字节)的影子内存,我们自然会想到,每字节内存的“中毒状态”只能通过影子内存上的一位来标记的。然而实际情况是,内存消毒剂在跟踪内存状态时,每字节使用一个整型值来记录。它假定所有“中毒内存”块都是连续的,且顺序从后往前,因此可以使用影子内存的一个字节来表示正常内存块中“中毒”的内存数量。例如:0表示所有内存都是正常的;1表示最后一个字节有问题;2表示最后两个字节有问题,依次类推,7表示这几个字节都有问题。若所有8字节都“中毒”,这个值就为负。使用这样的方式,就可以在访问内存的时候进行检查。分配内存的起始位置一般来说不会太过接近,因此,假定“中毒”内存是连续的且从后往前的, 这样不会带来什么问题。

有了这个表结构,地址消毒剂在程序中生成额外的代码来检查每次使用指针的读写操作,并在内存中毒的状态下抛出错误。该特性被集成在编译器中,而不仅仅在外部库和运行环境中存在,这样带来了不少好处:每个指针访问可被可靠地标识,并将合适的内存检查添加到机器码中。

编译器集成还支持一些简洁的技巧, 比如,除了堆(heap)上分配的内存外,可以跟踪保护本地和全局变量。本地和全局内存分配时会产生一些间隔,这些间隔内存若“中毒”可能导致溢出。这一点上,保护式内存分配无能为力,Valgrind也疲于应对。

编译器集成的特性也有其缺点。详细来说,地址消毒剂无法捕捉系统库中的错误内存访问。当然,它和系统库是“兼容”的。当使用系统库的时候,你可以打开内存消毒剂功能。比如,你可以构建一个链接Cocoa的程序,正常运行它。但是它不会捕捉Cocoa造成的错误内存访问,也无法检测你的代码调用Cocoa时分配的内存。

内存消毒剂也能用来捕捉“释放后使用”的错误。内存在释放后都会被标记为“中毒”,之后无法对其再进行访问。“释放后使用”的错误在内存重用时危害不浅,因为那样你会破坏不相关的数据。内存消毒剂会将刚释放的内存放置到一个回收队列中,在一段时间内将无法申请到这些内存,从而在重用时避免这样的错误。自然,为每个指针访问添加检查代价不小。它取决于代码做了什么,因为不同类型的代码访问指针内容的频率各不相同。平均算来,内存检查会降低大概2~5倍的速度,这个开销挺大,但还不至于让程序无法使用。

如何使用?

在Xcode 7上使用Address Sanitizer很简单。当通过命令行编译时,需要给clang命令调用添加-fsanitize=address参数。下面是一个测试程序:
26.png

编译,通过Address Sanitizer运行:
27.png27.png

程序立马crash,输出很多内容:

QQ截图20150729163210.png

这里包含很多信息,真实场景中,这些信息将对跟踪问题产生巨大帮助。它不仅显示了错误内存写入的位置,还标识了内存初始分配的位置。另外,还有其他附加信息。

在Xcode中使用内存消毒剂更简单:编辑scheme,点击Diagnostics标签页,选中"Enable Address Sanitizer"选项。然后就可以正常构建、运行,然后就能查看到大量诊断信息。

附加特性:不明确行为消毒剂

错误的内存访问只是C语言中诸多“有趣”的不明确行为的一种。Clang还提供了其他的消毒剂,使用它可以捕捉许多不明确行为。以下是实例程序:

1
2
3
4
5
6
7
    #include     #include     int main(int argc, char **argv) {
        int value = 1;
        for(int x = 0; x < atoi(argv[1]); x++) {
            value *= 10;
            printf("%d\n", value);
        }
    }

运行代码:

21.png21.png

结果的最后有些怪异。毫无疑问,有符号整形值溢出是C语言中的不明确行为。若能将这个错误捕捉,而不是产生错误的数据,就再好不过了。不明确行为消毒剂能有所帮助,传递-fsanitize=undefined-trap -fsanitize-undefined-trap-on-error参数来开启它:

22.png

这里并不像地址消毒剂那样输出额外的信息,但是,在出现错误的时候,程序立即停止了执行,而且我们通过调试工具可以很简单地查找问题。
不明确行为消毒剂暂时未集成到Xcode中,但是你可以在工程的build settings中添加compiler flags来使用。

结论

Address Sanitizer是一个伟大的技术,可以帮助我们查找到很多C代码中的问题。它并不完美,不能查找到所有错误,但仍能提供非常有用的诊断信息。在这里,我强烈建议你在自己的代码中尝试使用它,你会发现令你吃惊的结果。

5款免费二进制编辑器横向评测:从HxD到ImHex谁更适合你? 本文对5款免费二进制编辑软件进行深度横向评测,包括HxD、wxHexEditor、010 Editor、ImHex和GNU Emacs,涵盖从轻量级到专业级的各种需求。评测基于文件处理能力、编辑功能、分析工具等核心维度,为开发者、逆向工程师和安全研究人员提供实用选择指南,帮助用户根据具体场景选择最适合的二进制编辑工具。 阅读详情

相关推荐

【实战指南】Green Hills MULTI-IDE 从零安装到工程创建全流程

本文详细介绍了Green Hills MULTI-IDE从零安装到工程创建的全流程,包括系统要求检查、安装步骤、工程配置及调试技巧。特别适合嵌入式开发新手快速上手这款专业IDE工具,提升开发效率。

weixin_28740299的博客 474

Xcode特性Address Sanitizer,对比僵尸对象

昨天发现微博的圈子里iOS学习氛围比较好,所以特意注册了一个新浪微博。无意中在微博里看到了@没故事的卓同学的文章Xcode7中你一定要知道的炸裂调试神技,介绍Xcode7中新增了AddressSanitizer工具可以捕获EXC_BAD_ACCESS。然而Xcode中不是已经有了Zombie了么?怎么又出来了一个Address Sanitizer,他们有什么区别呢? AddressSanitizer VS Zombie 原理 zombie: zombie的原理是用生成僵尸对象来替换dealloc的实

gcs的博客 2711

文本→图像→视频:AIGC跨模态转换全流程解析

本文旨在系统性地解析AIGC领域中跨模态内容生成的技术原理和实现方法,特别聚焦于从文本到图像再到视频的完整转换流程。跨模态表示学习的基本原理文本到图像生成的核心技术图像到视频转换的关键算法端到端跨模态生成系统的构建方法实际应用场景和性能优化策略背景介绍:建立基本概念和知识框架核心概念:解析跨模态转换的关键技术和原理算法细节:深入讲解文本到图像、图像到视频的核心算法数学模型:提供必要的数学基础和公式推导项目实战:通过完整案例展示实现过程应用场景:探讨技术的实际应用可能性。

AI天才研究院 1353

在Xcode 7上直接使用Clang Address Sanitizer

原文:Address Sanitizer 在WWDC 2015上,除了Swift 2.0外,还有一个令人激动的消息:可以直接在Xcode 7上使用Clang的地址消毒剂(Address Sanitizer)了。这篇文章中我们将详细讨论下这个功能,比如它是怎样工作的,以及使用的方法。这是Konstantin Gonikman提议的话题。 C语言中一种异常危险的情况 从很多方面来

zhenganzhong_csdn的博客 886

LangGraph实战:用Python异步构建智能客服多轮对话系统(附完整代码)

本文详细介绍了如何使用LangGraph框架和Python异步编程构建一个高性能的智能客服多轮对话系统。通过将对话流程建模为有向图,结合thread_id实现多用户对话隔离,并利用异步节点提升系统并发处理能力,有效解决了传统客服系统上下文遗忘与高并发瓶颈问题。文章提供了从环境搭建、状态管理、异步优化到复杂业务逻辑与部署的完整实战代码。

weixin_29055137的博客 149

【AI 编程工具进阶用法】如何在Cursor、Trae等工具中使用Skills

OpenSkills是一个开源项目,用于在Cursor、Trae等AI编程工具中添加可复用、可组合的"能力模块"。安装流程包括:1)全局安装OpenSkills CLI工具;2)选择安装Anthropic官方Skills到项目或全局;3)创建AGENTS.md文件同步Skills;4)在AI工具中调用Skills。此外还介绍了UI/UX Pro Max Skill项目,通过npm安装后可为AI添加设计能力。这些Skills相当于为AI工具安装"高级技能包"

肌肉金轮的博客 3544

Xcode7中你一定要知道的炸裂调试神技

源地址:http://www.jianshu.com/p/70ed36cf8a98 Xcode7中苹果为我们增加了两个重要的debug相关功能。了解之后觉得非常实用,介绍给大家。 1.Address Sanitizer: 妈妈再也不用担心 EXC_BAD_ACCESS  EXC_BAD_ACCESS一直是很多开发者的噩梦,因为这个错误很不直观,出现后往往要花很长时间才能定位到

 ideaOS^(BOOL coding) 866

RK3568平台(USB篇)USB基础知识

现象:把USB设备比如Android手机接到PC答1:是USB控制器,是USB控制器内嵌的root hub.答2. windows里已经有了USB的总线驱动程序,接入USB设备后,是"总线驱动程序"知道你是"android phone"提示你安装的是"设备驱动程序"。USB总线驱动程序负责:识别USB设备, 给USB设备找到对应的驱动程序。答3. PC的USB口内部,D-和D+接有15K的下拉电阻,未接USB设备时为低电平USB设备的USB口内部,D-或D+接有1.5K的上拉电阻;

weixin_49303682的博客 1658

使用Clang作为编译器 —— AddressSanitizer

AddressSanitizer(未完成)1. 介绍2. 如何构建3. 使用(Usage)4. 用符号表现报告(Symbolizing the Reports)5. 额外的检查(Additional Checks)5.1 初始化顺序检查(Initialization order checking)5.2 内存泄漏检测(Memory leak detection)6. 问题抑制(Issue Supp...

梦在哪里的博客 5880

2026华为OD机试 新系统真题题库目录|机考题库 + 算法考点详解

华为OD机试 新系统真题题库目录|机考题库 + 算法考点详解华为od机试,华为od机试真题,华为od机试E卷,华为odE卷,华为od机试真题E卷,华为OD,华为OD机试,华为OD机试真题,华为od机考,华为od机试D卷,华为od机试真题D卷,华为od手撕代码,华为od,华为od机试C卷,华为od e卷,华为2026e卷,od机试,2026E卷,华为OD机试E卷,什么是华为od,华为od介绍,全面了解华为od,2026华为od,如何备战华为od,华为od算法,华为od手撕代码,华为OD机试2024年最新题库,

KJ.JK 4696

华为OD机试 - 小火车最多人时所在园区站点(Java 2024 E卷 100分)

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、发现新题目,随时更新,全天优快云在线答疑。

学Java,找哪吒 996

(转)在Xcode 7上直接使用Clang Address Sanitizer

原文地址: http://www.cocoachina.com/ios/20150730/12830.html WWDC 2015上,除了Swift 2.0外,还有一个令人激动的消息:可以直接在Xcode 7上使用Clang的地址消毒剂(Address Sanitizer)了。这篇文章中我们将详细讨论下这个功能,比如它是怎样工作的,以及使用的方法。这是Konstantin Gonikman提议...

weixin_30725467的博客 127

【WorkBuddy专栏19】技能的创造与迁移——从零开始打造你的AI工作流

【WorkBuddy专栏19】技能的创造与迁移——从零开始打造你的AI工作流

AI人人懂 372

Clang Address Sanitizer

在Xcode 7上直接使用Clang Address Sanitizer 2015-07-30 10:08 编辑: suiling 分类:iOS开发 来源:Mike Ash 1 13332 Xcode 7 招聘信息: Web后端高级开发工程师iOS软件工程师java高级软件工程师高级iOS开发工程师高级PHP开发工程师iOS高级研发工程师iOS开发

xumugui007的博客 739

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Xcode7 新升级,Address Sanitizer: 必杀解决 EXC_BAD_ACCESS

EXC_BAD_ACCESS一直是很多开发者的噩梦,因为这个错误很不直观,出现后往往要花很长时间才能定位到错误。苹果这次带来了革命性的提升。 在项目的Scheme中Diagnostics下,选中enable address sanitizer(注意选中后Xcode会重新编译整个项目)。 这样设置后,如果再出现类似的错误会有更详细的错误信息提示,甚至会有内

shly1988的博客 525

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Xcode 7 调试野指针利器 Address sanitizer

什么是Address Sanitizer? AddressSanitizer is a fast memory error detector. It consists of a compiler instrumentation module and a run-time library. The tool can detect the following types of bugs: Out-

SuYuMingXiangGuan的博客 3238

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Xcode7调试Address Sanitizer扫尾

Xcode7中你一定要知道的炸裂调试神技 真机调试完成后记得关闭Address Sanitizer选项,否则会造成iPhone断开电脑后无法启动所调试的应用! 真机调试完成后记得关闭Address Sanitizer选项,否则会造成iPhone断开电脑后无法启动所调试的应用! 真机调试完成后记得关闭Address Sanitizer选项,否则会造成iPhone断开电脑后无法启动所调试的应

谁令骑马客京华 936

Xcode调试技巧大全,资深iOS工程师每天都在用的7个隐藏功能

掌握Xcode高效调试技巧,助力ios程序员学习路径进阶。分享7个资深工程师常用隐藏功能,涵盖断点调试、内存分析、视图层级排查等实用场景,提升开发效率与问题定位速度。值得收藏

ProceGlow的博客 666

iOS开发之调试技巧Xcode7中你一定要知道的炸裂调试神技、Address Sanitizer EXC_BAD_ACCESS

Xcode7中苹果为我们增加了两个重要的debug相关功能。了解之后觉得非常实用,介绍给大家。 1.Address Sanitizer: 妈妈再也不用担心 EXC_BAD_ACCESS  EXC_BAD_ACCESS一直是很多开发者的噩梦,因为这个错误很不直观,出现后往往要花很长时间才能定位到错误。苹果这次带来了革命性的提升。 在项目的Scheme中Diagnostics下,选中enab

zhonggaorong的专栏 2137

NSLog,LLDB, Breakpoint,EXC_BAD_ACCESS,Address Sanitizer ,iOS开发之Xcode常用调试技巧总结

一、Xcode调试技巧之:NSLog 上面也提到了,在我们日常的开发过程中最常见的Debug方式就是打Log。而在OC语言中,打Log是采用NSLog方法。但是NSLog效率低下,具体原因可以看这篇博客(《NSLog效率低下的原因及尝试lldb断点打印Log》)。所以在平时的开发过程中,能不打Log就不打Log。实在想打Log网上也有对NSLog的一些优化方法,可以阅读王巍的《宏定义的黑魔法

viiimaus的博客 1544

【iOS开发】Xcode 调试野指针利器 Address sanitizer

转载地址:https://www.cnblogs.com/xitang/p/4904405.html

Hanrovey Blog 2495

解决XCode 7 AddressSanitizer: heap-buffer-overflow的问题

看到苹果系统发布了新版本,禁不住升级了,用了xcode 7。后来不知啥时候开启了AddressSanitizer,再后来调试的时候,突然就挂了,出的问题就是==12463==ERROR: AddressSanitizer: heap-buffer-overflow on address。而且这个开启后,就是在用XCode安装App到设备后,点击XCode的停止,再直接在设备上点击App,就会闪退。关

yqmfly的专栏 6563

Xcode的诊断配置

Xcode的scheme配置中,有个Diagnostics栏目,其中有很多内存相关的配置,用来帮助开发者定位内存问题。常用的功能有这些。 Address Sanitizer Guard Malloc Zombie Objects Malloc Scribble Maloc Guard Edges Malloc Stack LoggingAddress Sanitizer,地址消毒剂 Guard Malloc Malloc Scribble,将分配的内存填充0xAA(通过malloc调用的,calloc不会填

勿在浮沙筑高楼 1299

关于Xcode 检查内存泄露方法

一、Xcode -> product ->Analyze  eg:项目中会提示 二、Xcode -> profile -> leakS 双击后跳出对应代码位置 三、Xcode7 检查内存 使用  内存消毒剂  Enable Address Sanitizer  在Xcode中使用内存消毒剂更简单:编辑scheme,点击Diagnostics标签页,选中"Enabl

i_k_o_x_s的专栏 1306
上一篇: iOS快速开发必备
下一篇: iOS 事件处理机制与图像渲染过程
潘柏信
博客等级 码龄11年 3粉丝 5原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值