首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

先别急着“用Rust重写”,可能没有说的那么安全

,Rust 和 C 对于其中的 a 和 b 分别做出了不同假设,而且从 C 调用 add_twice(&bar, &bar) 会导致未定义行为。...然而,C 和 Rust 代码联合体静默调用了未定义的行为,结合具体的架构、Rust 版本和 LLVM 版本,这有可能引发内存安全问题。 在实践当中,这个问题不涉及人为因素,而且很难加以预防。...其实这个问题不仅困扰 Rust,FFI 是出了名的棘手且极易引发错误,即使 Rust 也难以将其“驯服”。...我们将本节内的问题划分成以下几类:首先是内存时空安全;其次是异常问题中的一类常见错误——跨 FFI 边界展开堆栈属于未定义行为,因此可能构成难以察觉的严重故障;第三是类型安全和 Rust 关键不变量相关的错误...其他未定义行为 还有其他一些更加“玄幻”的未定义行为,主要涉及不同语言的细节和架构 ABI(应用程序二进制接口)的特殊约定。 胶水代码。

43430

目前CSDN上最全面的C语言讲解如何用更高层次编写嵌入式C代码

,介绍了该编译器的特性、对未定义行为的处理以及一些高级应用;在此基础上,介绍了防御性编程的概念,提出了编程过程中就应该防范于未然的多种措施;提出了测试对编写优质嵌入式程序的重要作用以及常用测试方法;最后...现在它跳出了switch语句,执行了use_modes_pointer()函数。但必要的初始化工作并未完成,为将来程序的失败埋下了伏笔。...C标准委员会定义未定义行为的原因如下: 简化标准,并给予实现一定的灵活性,比如不捕捉那些难以诊断的程序错误; 编译器开发商可以通过未定义行为对语言进行扩展 C语言的未定义行为,使得C极度高效灵活并且给编译器实现带来了方便...但是还是有一些方法可以降低这种事件,总结如下: 了解C语言未定义行为 标准C99附录J.2“未定义行为”列举了C99中的显式未定义行为,通过查看该文档,了解那些行为是未定义的,并在编码中时刻保持警惕;...这是一个经常会遇到的事情,举一个例子,程序中的一个变量在运行时总是不正常的被改变,那么有理由怀疑它临近的变量或数组溢出了,溢出的数据更改了这个变量值。

2.4K21
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    JS到底是怎么执行的:一文彻底搞清执行上下文

    在开始之前,你需要先熟悉一些概念,因为我们将在本文中经常用到它们: 解析器: 语法解析器是一个逐行读取代码的程序。它理解代码如何符合编程语言定义的语法,以及代码应该做什么。...它们通常在语句中使用,比如将函数赋值给变量: let someValue = function(){ //statements } 现在,我们已经知道了这些概念,让我们开始吧。...函数提升 在大多数情况下,当构建一个应用程序时,开发人员可以选择在脚本的顶部定义函数,然后在代码中调用它们,就像这样: 但是,由于提升的原因,这段代码仍然可以工作。...为了理解执行堆栈的工作过程,考虑下面的代码示例: var name = "Victor"; function first() { var a = "Hi!"...当JS引擎遇到first()函数调用时,会为它创建一个新的FEC。这个新上下文被置于当前上下文的顶部,形成了所谓的执行堆栈。

    1.4K60

    37个JavaScript基本面试问题和解答(建议收藏)

    (这就是为什么你应该在你的代码中使用strict,一个重要的例子!) 3、下面的代码将输出到控制台的是什么?,为什么?...他们都会返回同样的值吗?为什么或者为什么不?...由于代码的其余部分是完全有效的,即使它没有被调用或做任何事情(它只是一个未使用的代码块,它定义了一个属性栏,它等于字符串“hello”),所以不会抛出任何错误。...为什么? (b) 提供一个或多个可按预期工作的替代实现。 答: (a) 无论用户点击哪个按钮,数字5将始终记录到控制台。...16、如果数组列表太大,以下递归代码将导致堆栈溢出。你如何解决这个问题,仍然保留递归模式?

    3K10

    JS 到底是在干嘛:一文搞懂JS 执行上下文

    在开始之前,你需要先熟悉一些概念,因为我们将在本文中经常用到它们: 解析器: 语法解析器是一个逐行读取代码的程序。它理解代码如何符合编程语言定义的语法,以及代码应该做什么。...它们通常在语句中使用,比如将函数赋值给变量: let someValue = function(){ //statements } 现在,我们已经知道了这些概念,让我们开始吧。...函数提升 在大多数情况下,当构建一个应用程序时,开发人员可以选择在脚本的顶部定义函数,然后在代码中调用它们,就像这样: 但是,由于提升的原因,这段代码仍然可以工作。...当JS引擎遇到first()函数调用时,会为它创建一个新的FEC。这个新上下文被置于当前上下文的顶部,形成了所谓的执行堆栈。...不创建“this”对象,但是可以访问定义它的环境的对象。通常是window对象。

    43410

    STM32编程:是时候深入理解栈了

    FIQ FIQ_STACK 用于高速(FIQ)中断处理程序的堆栈。 Undefined UND_STACK 堆栈用于未定义的指令中断。 支持硬件协处理器和指令集扩展的软件仿真。...Abort ABT_STACK 用于指令获取和数据访问存储器中止中断处理程序的堆栈。...image-20200419163415180.png 图为什么没有将0x2000 07D8画在栈区呢?通过调试发现,这个字空间没有用做栈的实际存储。...将n改为21编译运行,来看一看: stackOverflow_zhihu.gif 看到了吧,惊喜来了,栈溢出了,程序已经不听话了,完全不知道在干嘛了。...总结一下 栈是一种LIFO后入先出的数据结构模型,是C/C++程序运行时基础,没这个栈,C/C++玩不转 栈在嵌入式编程领域随处可见,比如C栈,中断栈、异常栈、任务栈等等,但其基本工作原理都一样。

    1.2K00

    JavaScript 编程精解 中文第三版 八、Bug 和错误

    我们知道程序运行出了问题,试图找出其原因。 这是一个地方,你必须抵制随机更改代码来查看它是否变得更好的冲动。 相反,要思考。 分析正在发生的事情,并提出为什么可能发生的理论。...然后,再做一些观察来检验这个理论 - 或者,如果你还没有理论,可以进一步观察来帮助你想出一个理论。 有目的地在程序中使用console.log来查看程序当前的运行状态,是一种不错的获取额外信息的方法。...但是如果你创建了一些将被其他人使用的东西,你通常希望程序比只是崩溃做得更好。 有时候,正确的做法是不择手段地继续运行。 在其他情况下,最好向用户报告出了什么问题然后放弃。...如果异常总是会将堆栈尺寸缩减到栈底,那么异常也就毫无用处了。它只不过是换了一种方式来彻底破坏你的程序罢了。异常真正强大的地方在于你可以在堆栈上设置一个“障碍物”,当异常缩减堆栈到达这个位置时会被捕获。...这使得这种错误不太可能被忽视,并且当它们发生时更容易找到它们的原因。 我不建议尝试为每种可能的不良输入编写断言。 这将是很多工作,并会产生非常杂乱的代码。

    1.2K100

    Unsafe 随堂小测题解(一)

    官方给出的解释为: “健全性是一个类型系统的概念,意味着类型系统是正确的,即,类型良好的程序实际上应该具有该属性。对于 Rust 来说,意味着类型良好的程序不会导致未定义行为。...但是这个承诺只适用于 Safe Rust。对于 Unsafe Rust要有开发者/程序员来维护这个契约。因此,如果Safe 代码的公开 API 不可能导致未定义行为,就可以说这个库是健全的。...反之,如果安全代码导致未定义行为,那么这个库就是不健全的。 也就是说,开发者在编写 Unsafe Rust 代码的时候,有义务来保证提供的安全抽象接口是不会有未定义行为产生的。...违反了健全性,就是不健全(Unsound)的。 未定义行为 (Undefined Behavior) 的准确定义,可以参加上面提到的术语指南。 在对这两个基本术语了解以后,我们就可以来解题了。...val 也是内存对齐的,因为它使用了引用。

    96120

    几个嵌入式项目中的技巧!

    今天给大家介绍7个易操作且可以长久使用的技巧,它们对于确保系统更加可靠地运行并捕获异常行为大有帮助。...如果系统出了某些差错,处理器开始执行程序空间以外的代码,就会触发ISR,并在决定校正行动之前提供储存处理器、寄存器和系统状态的机会。...技巧2---检查应用程序的CRC对嵌入式工程师来说一个很大的好处是,我们的IDE和工具链可以自动产生应用程序或内存空间校验和(Checksum),从而根据这个校验和验证应用程序是否完好。...毕竟,这是一种常在计算器系统中使用的技术,在计算器系统中,只有在有必要时,内存才会被分配。例如,以C开发时,工程师可能倾向于使用malloc来分配在堆(heap)上的空间。...如果出现这些问题时,大多数的嵌入式系统并没有 资源或知识来监视堆或妥善地处理它。而当它们发生时,如果应用程序提出对空间的要求,但却没有所请求的空间可以使用,会发生什么事呢?

    20620

    C++(STL3)容器适配器(1) stack,queue and priority_queue

    下面展示了如何定义一个使用 list 的堆栈: std::stack> fruit; 创建堆栈时,不能在初始化列表中用对象来初始化...,但是可以用另一个容器来初始化,只要堆栈的底层容器类型和这个容器的类型相同。...可以用stack 实现一个简单的计算器程序,如下: // A simple calculator using stack containers #include ...只能在容器的末尾添加新元素,只能从头部移除元素。 许多程序都使用了 queue 容器。queue 容器可以用来表示超市的结账队列或服务器上等待执行的数据库事务队列。...2.函数操作 queue 和 stack 有一些成员函数相似,但在一些情况下,工作方式有些不同: front():返回 queue 中第一个元素的引用。

    68430

    你所能用到的数据结构(八)

    C++或者什么语言编程里面,不需要引用什么头文件就可以像声明数组一样声明一个堆栈,然后很方便的就可以使用这个结构。...因为括号都是成对出现的,但是在一个程序中就括号而言完全可能出现{()}这样的顺序,先观察一下,发现如果括号是匹配的,无论的括号之间的包含关系是什么,那么当出现右括号时,它的前一个不是对应的左括号,那么一定是不匹配的...,那么什么也不做(当然,这里可以优化成为如果不匹配直接结束),这样,最终完全匹配的条件就是在程序将符号全部读完之后,堆栈是空的,不然都为不匹配。...第一个应用很简单,第二个应用也是每本书上都会用的逆波兰表达式,为什么我还是觉得应该举这个例子呢?...让计算机在看到这个算式的时候不是得出7而是得出6,再通俗一点怎样让计算机从普通计算器进化到科学计算器?

    63640

    Reddit 观察 | 以排序为案例,对 CCPPRust 安全与性能的相关性研究

    即使只使用内存安全的抽象来实现排序,也不能保证相邻逻辑是无未定义行为的。 总体而言,性能和安全之间没有明显的相关性,无论是使用安全还是不安全的内部抽象。...比如导致CPU MMU异常的越界读取、非法CPU指令、堆栈溢出、改变无关程序状态等等。 可能你会有疑问,排序只不过是这些数字的比较和位置交换,怎么可能会产生 UB 呢?...它们的析构函数将传递一个指向分配器的指针以进行释放。位拷贝会导致使用后释放的未定义行为,很可能以双重释放的形式出现。...如果在排序完成后没有观察到这种修改,依赖于空指针检查来判断是否已经释放的代码将遇到使用已释放内存的未定义行为。...新的、迄今为止未经测试的 libc++ 实现在某些分析过的安全特性上表现出了一定的意识,主要是 Ord 安全性,但未能找到一种保证无未定义行为(UB)的使用方式。它只能执行可选的越界检查。

    40120

    为什么我十分喜欢C,却很不喜欢C++?

    为什么说C不是最好的语言? 首先,这个世上没有最好的编程语言。每种语言都有独特的优势以及适用情况,所以尽管你可以在 Excel 中编写光线追踪程序,但最好还是使用其他语言。...拥有 RAII 概念:一个简单的例子就是 C++ 拥有构造函数,可在创建对象时初始化对象;还拥有析构函数,在销毁对象时,做一些清理的工作。这个概念进一步发展,就接近 Rust 的生命周期了。...当然我指的是“未定义的行为”以及编译器的处理方式。这已成为一大毒瘤(只要你的代码依赖于二进制补码算术,就会被认定具有未定义的行为,编译器会抛弃整块代码)。...例如,无法使用两个不同类型的指针同时操作同一块内存区域。我无法想象为什么这种行为被禁止,其原因只可能是编译器优化。这样就不可能利用联合体将整数转换成浮点数。...总结 总的来说,我喜欢C所处的中层位置,它既可以完成一些底层的实现,例如轻松地操作内存,同时又可以享受高级语言的好处。

    78610

    C语言不是最好的,却是我最爱的~

    1、为什么说C不是最好的语言? 首先,这个世上没有最好的编程语言。每种语言都有独特的优势以及适用情况,所以尽管你可以在 Excel 中编写光线追踪程序,但最好还是使用其他语言。...拥有 RAII 概念:一个简单的例子就是 C++ 拥有构造函数,可在创建对象时初始化对象;还拥有析构函数,在销毁对象时,做一些清理的工作。这个概念进一步发展,就接近 Rust 的生命周期了。...当然我指的是“未定义的行为”以及编译器的处理方式。这已成为一大毒瘤(只要你的代码依赖于二进制补码算术,就会被认定具有未定义的行为,编译器会抛弃整块代码)。...例如,无法使用两个不同类型的指针同时操作同一块内存区域。我无法想象为什么这种行为被禁止,其原因只可能是编译器优化。这样就不可能利用联合体将整数转换成浮点数。...5、总 结 总的来说,我喜欢C所处的中层位置,它既可以完成一些底层的实现,例如轻松地操作内存,同时又可以享受高级语言的好处。

    17510

    有效处理Java异常的三个原则,你知道吗?

    为什么出错? 在有效使用异常的情况下,异常类型回答了“什么”被抛出,异常堆栈跟踪回答了“在哪“抛出,异常信息回答了“为什么“会抛出,如果你的异常没有回答以上全部问题,那么可能你没有很好地使用它们。...每一种都描述了一类特定的I/O错误:分别是文件丢失,异常文件结尾和错误的序列化对象流.异常越具体,我们的程序就能更好地回答”什么出了错”这个问题。 捕获异常时尽量明确也很重要。...举例来说:如果捕获了FileNotFoundException,它可以提示用户指定另一 个文件,某些情况下多个catch块带来的额外编码工作量可能是非必要的负担,但在这个例子中,额外的代码的确帮助程序提供了对用户更友好的响应...堆栈信息立即反映出什么出了错(提供了非法参数值),为什么出错(文件名不能为空值),以及哪里出的错(readPreferences()的前部分)。这样我们的堆栈信息就能如实提供: ?...延迟捕获 菜鸟和高手都可能犯的一个错是在程序有能力处理异常之前就捕获它。Java编译器通过要求检查出的异常必须被捕获或抛出而间接助长了这种行为。

    1.6K10

    译文:开发人员面临的 10个最常见的JavaScript 问题

    今天,JavaScript是几乎所有现代Web应用程序的核心。这就是为什么JavaScript问题,以及找到导致它们的错误,是Web开发人员的最前沿的问题。...而且,仅在实际上从未使用过replaceThing的功能的主体和函数中引用。 因此,我们再次想知道为什么这里存在内存泄漏。 为了理解发生了什么,我们需要更好地了解JavaScript的内部工作原理。...以下是我们如何纠正JavaScript的上述问题,以实现预期行为: 在这个修订后的代码版本中,每次我们通过循环时都会立即执行makeHandler,每次收到i+1的当前值并将其绑定到作用域num变量。...eval()在严格模式和非严格模式下的行为方式存在一些差异。最重要的是,在严格模式下,在eval()语句中声明的变量和函数不会在包含范围内创建。...写在最后 与任何技术一样,你越了解JavaScript为什么以及如何工作和不起作用,你的代码就越可靠,你就越能有效地利用语言的真正力量。

    1.3K20

    嵌入式系统常用的7个技巧

    给大家介绍7个比较好操作且可以长久使用的技巧,它们对于确保系统更加可靠地运行并捕获异常行为大有帮助 技巧1——用已知值填充ROM 软件开发人员往往都是非常乐观的一群人,只要让他们的代码忠实地长时间地运行就可以了...如果系统出了某些差错,处理器开始执行程序空间以外的代码,就会触发ISR,并在决定校正行动之前提供储存处理器、寄存器和系统状态的机会。...技巧2——检查应用程序的CRC 对嵌入式工程师来说一个很大的好处是,我们的IDE和工具链可以自动产生应用程序或内存空间校验和(Checksum),从而根据这个校验和验证应用程序是否完好。...现在一个编程过的应用程序发生改变的概率是很小的,但考虑每年交付的数十亿个微控制器以及可能恶劣的工作环境,应用程序崩溃的机会并不是零。...毕竟,这是一种常在计算器系统中使用的技术,在计算器系统中,只有在有必要时,内存才会被分配。例如,以C开发时,工程师可能倾向于使用malloc来分配在堆(heap)上的空间。

    45010

    数据结构与算法:递归算法

    重要的是要知道我们应该提供某种情况来终止这个递归过程。 所以我们可以说,每次函数调用自身时都会使用原始问题的简单版本。...为什么需要递归 递归是一项令人惊奇的技术,借助它我们可以减少代码的长度并使其更易于阅读和编写。与稍后将讨论的迭代技术相比,它具有某些优点。...,最后,这是程序员手中的一个很好的工具,可以以更简单有效的方式编写一些问题。...阶乘的基本情况是 n = 0。当 n = 0 时,我们返回 1。 为什么递归会出现Stack Overflow错误? 如果未达到或未定义基本情况,则可能会出现堆栈溢出问题。...使用递归解决的实际问题并了解其基本工作原理 问题 1: 编写一个递归关系程序来查找 n 的斐波那契数列,其中 n>2 。

    19410
    领券