首页 >>  正文

c语言功能结构图

来源:baiyundou.net   日期:2024-09-23

【CSDN 编者按】在研发过程中,编程语言的优劣对应用程序的性能有着巨大的影响。近些年间,随着应用程序规模的扩大,越来越多的公司开始关注其安全性能,如 Google、微软、亚马逊等科技巨头纷纷开始推荐 Rust 这类为安全而生的语言,欲取代过往的 C/C++,甚至美国国家安全局也于不久之前发布建议:弃用 C/C++,使用更安全的 Rust、C# 等!

不过,在本文作者、也是一位软件开发者、计算系统设计师看来,Rust、C++ 都没有 C 香,以下他列出了 7 大理由!

原文链接:https://gavinhoward.com/2023/02/why-i-use-c-when-i-believe-in-memory-safety/

声明:本文为 CSDN 翻译,未经允许,禁止转载。

作者 | Gavin Daniel Howard

译者 | 弯月 责编 | 屠敏

出品 | CSDN(ID:CSDNnews)

最近,美国国家安全局发布了一些关于软件内存安全的建议(https://media.defense.gov/2022/Nov/10/2003112742/-1/-1/0/CSI_SOFTWARE_MEMORY_SAFETY.PDF):

其鼓励多个组织将编程语言从 C/C++ 转为使用内存安全的语言,如 C#、Rust、Go、Java、Ruby 和 Swift,主要原因是这样可以帮助软件开发者和使用者预防并缓解软件内存安全问题,这些问题占可利用漏洞的很大一部分。

这份文档引起了很大骚动。其实,这些都是常识性建议,如非有充分的理由,我们都应该遵循这些建议。

不过,C++ 之父 Bjarne Stroustrup 认为 C++ 并没有那么糟,他表示美国国家安全局忽略了 C/C++ 三十多年来的进步。

Bjarne Stroustrup 还说:

“例如,Microsoft Visual Studio 分析器和内存安全评测器已能提供大部分的 CG 支持,而现在任何优秀的静态分析器(例如 Clang tidy 就提供了部分 CG 支持)都可以设置为提供这样的保证……”

但我非常不赞同这个观点。事实上,我认为 C++ 的复杂性使其比 C 更糟。

美国国家安全局人员 Jimmy Hartzel 如此评价,我非常同意他的看法:

“就内存安全而言,‘大部分’是完全不够的,而‘可以设置为’实际上也没有价值。从根本上来看,关键的一点是 C++ 的内存安全仍在积极开发中,已经很接近其他的语言了。同时,Rust(和 Swift、C#、Java 等)已经实现了内存安全。”

虽然我不太喜欢 Rust,但不可否认的是,Rust 是当前 C 或 C++ 程序员的最佳选择。

然而,我的当前项目仍然是用 C 语言编写的。

为什么我这么喜欢 C 语言?理由如下。

文档

第一个理由是,我可以记录一切。

从很多方面来说,Rust 很棒,而且该语言本身也很擅长提供代码的文档。

例如,对于显式指针类型,很容易看出如何正确使用函数的参数。

C 只有值和指针类型。指针可以动态分配或指向祖先栈中的某些元素。但也可以是完全不相关的东西。

Rust 具有更好的类型安全。你给 C void*,它会欣欣然接受这个有可能指向任何东西的指针。

客观地说,从这些方面来看,Rust 的表现更好。

我通过各种方式来写文档:

记录所有能想到的假设,而且通常是在代码中利用断言来记录。

记录每个函数及其参数和用途。

记录每个结构、每个字段、每个枚举。

我还写了很多设计文档和开发文档。

如此一来,我不仅享受到了 Rust 的许多优点,而且还有很好的文档,这对我的用户来说无疑是一件好事。

我并不是说 Rust 更好,只不过这样可以迫使我编写文档。

单独工作

其次,我需要独自将脑海中的想法变成代码。

Rust 非常适合团队,因为它消除了许多团队合作编写代码时的风险因素。

然而,我是单独工作,因为我喜欢把代码记在脑子里,与他人一起工作则意味着部分代码只在他们的脑子里。

这也意味着,语言越大,我脑子里留给代码的空间就越少。

不幸的是, 对于我的小脑袋来说,Rust 太大了。

我觉得 Rust 不够有趣

这引出了下一个原因:我不喜欢 Rust。

注意,这纯粹是个人喜好, 我并不是说 Rust 不好。

我使用过很多语言编写代码:

C

C++

Rust

Haskell

Go

Python

PHP

Ruby

Zig

Bash

POSIX sh

bc

dc

JavaScript

Clojure

Java

C#

Various assembly languages

GLSL

Common Lisp

Racket

Julia

Tcl

Vim script

此外,我还研究过以下语言:

ML

OCaml

HAL/S

Pascal

Objective-C

MATLAB

Modula-2

Coq

Isabelle/HOL

Ada/SPARK

等等。

若论编程的乐趣,我讨厌所有这些语言。除了 C 语言。

没错,C 是唯一我真正喜欢的编程语言。

我不是在说笑,相较于其他语言,我用 C 编写代码的效率高出几个数量级。我的脑子只适合用 C 思考,我也不知道为什么。

这对我来说非常重要。根据以往的经验,我是一个很容易情绪化的程序员,如果周遭的环境不合适,我就无法有效地编程。

如果累了,我就无法有效地编程。

如果一边写代码一边听音乐,我也无法有效地编程。

如果被一项任务压得喘不过气来,我就无法有效地编程。

如果无法想象整个软件,我就无法有效地编程。

如果老婆跟我闹脾气,我就无法有效地编程。

最后,我无法使用不喜欢的语言进行有效的编程。

我曾经拒绝过一份工作邀请,因为他们使用的是 C++,而我讨厌 C++。

所以我不使用 Rust 或其他内存安全语言,因为我已经尝试过,但我无法使用这些语言有效地编程。

我知道这是个人问题,跟 Rust 无关。

但是,我很擅长 C 语言,虽然并不完美。

自律

这引出了我的下一个原因:我很自律,而且能通过这种能力编写高水平的 C 代码。

我的自律可以通过多种形式表现出来:

我只使用无符号整数,以此避免未定义的行为。我甚至会使用无符号整数模拟有符号的二补数。

如果我编写的函数的返回值没有被使用,我会使用一个宏让 Clang 报错。

我使用 -Wall、-pedantic 和 -Werror 来运行 Clang 和 GCC。 这意味着,我在开发的阶段就消除了警告。

我甚至用 -Weverything 运行 Clang,除了 -Wpadded,因为我不关心结构中的填充(我会仔细安排它们的布局);还有-Wc++98-compat,因为我不关心 C++ 98 兼容性 ,因为它与 C11 stdalign.h 相互干扰。

我会在测试套件中运行健全性测试,并消除一切错误。是的,一切,甚至是误报。

我会在测试套件中运行 Valgrind,并消除一切错误。

我会在测试套件中运行 Helgrind ,并消除一切错误,甚至是误报。

我会运行静态分析,并消除一切错误,甚至是误报。

你不了解一次又一次地运行 Valgrind、Clang、ASan 或 TSan,一次又一次地消灭 bug,最后什么都不剩下的感觉有多么好。

我感到无比的幸福和满足。

这也算是一种编程强迫症吧。

经验

下一个原因:经验。

我花了很多时间用 C 来解决各种 bug,因此我花在 C 上的时间远超其他编程语言。我对 C 语言的了解远胜其他语言。

这种经验上的差距很难弥补。如果从今天开始使用 Rust,我相信我需要大约十年的时间才能像 C 一样精通 Rust。

为此,我需要付出大量的时间。

编译时间

下一个核心原因:编译时间。

我知道如今 Rust 已经得到了很大提升,非常棒。

但 Rust 仍然很慢。我的电脑是 16 核的,在相同的时间里,用 C 语言我可以构建整个项目(包括测试套件),而用 Rust 我只能构建一个文件。

另一个方面是 C 文件包含模型,尽管不尽如人意,而且并行非常尴尬。Rust 很好,只不过还没有那么好。

自定义内存安全

下一个原因是,在使用 C 语言期间,关于内存安全,我已经开发出了自己的软件设计风格。

我使用特殊的数组类型来代替普通指针,这些数组会存储自己的边界。

我有一些宏,在访问数组索引时会进行边界检查。

我有一些宏,在计算数组指针时会进行边界检查。

我有一个栈分配器,我可以借助这个栈分配器在每个平台上实现 alloca() 。

我可以借助栈分配器将每个分配都放在同一个栈帧内。

栈分配器知道析构函数,因此它会在释放内存时调用析构函数。

如果我调用一个特定的函数,栈分配器会释放作用域内分配的所有内存。

如果我调用一个特定的函数,栈分配器会释放函数中分配的所有内存。

我使用结构化并发,这意味着如果将数据传递给新线程,我可以确保线程的寿命不会超过传递给它的数据。

简而言之,每条数据都可以追溯栈中特定位置上的祖先,数据永远不会传递给生命周期有可能超过自己的对象。

也就是我们常说的RAII(Resource Acquisition Is Initialization,资源获取即初始化),这意味着我能够控制生命周期和所有权,可以使用借用,以及我用 C11 重写了 Rust 的精华部分。

一般来说,让编译器静态地强制一切规则是最好的。

所有这一切都意味着,内存的分配和释放必须在同一个函数内,或者作为父对象的一部分被释放。

这大大减少了双重释放和释放后使用。因为我的所有代码都采用了这种写法,无一例外,所以我可以通过充分的测试来消除所有错误。

此外,边界检查可以大幅减少缓冲区溢出。

当然,引用 Jimmy Hartzell 的一句话:任何不完美的东西都不够好。

换句话说,我使用的不是 C 语言,而是内存安全的 C 语言。

总结

所以,上述就是我坚持使用 C 语言的全部理由。

当然,你有可能不同意我的看法。

只不过,我这个人遇到不喜欢的软件,就无法享受编写的过程。而我只喜欢 C 语言。

所以,对我个人而言,坚持使用 C 仍然是不二的选择。

","force_purephv":"0","gnid":"9248e5d7e808e130e","img_data":[{"flag":2,"img":[{"desc":"","height":"80","s_url":"https://p0.ssl.img.360kuai.com/t0186957a1ca5352752_1.gif","title":"","url":"https://p0.ssl.img.360kuai.com/t0186957a1ca5352752.gif","width":"640"}]}],"original":0,"pat":"art_src_1,fts0,sts0","powerby":"cache","pub_time":1675907293000,"pure":"","rawurl":"http://zm.news.so.com/e3c00a04a7df58594e684850baeba775","redirect":0,"rptid":"e7fdb7bbbee9bcd3","s":"t","src":"CSDN","tag":[{"clk":"ktechnology_1:tcl","k":"tcl","u":""},{"clk":"ktechnology_1:内存","k":"内存","u":""}],"title":"为什么我相信使用 C 语言可以保证内存安全?

蒲国券4009C语言程序的结构特点
寇要司13457387893 ______ C语言程序的结构特点有:顺序结构,循环结构和选择结构.

蒲国券4009c语言有哪几种流程结构?具体在程序中用什么体现? -
寇要司13457387893 ______ 顺序,选择(条件),循环三种 顺序的实现方式就是一条一条的罗列语句,每条语句后面用分号分隔 选择就是if(条件表达式){}else{}或者switch语句 循环有while语句 do-while语句 for语句

蒲国券4009C语言 主要程序流程图 -
寇要司13457387893 ______ 简单地来说流程图就是使用图形表示算法的思路的一种极好的方法,因为千言万语不如一张图.主要由顺序结构,分支结构(又称选择结构),循环结构构成.建议去看一看谭浩强编写的C程序设计,里面有一个章节专门讲这个的,简单易懂,相信你能在短时间内就掌握这种表示方法的.

蒲国券4009c语言程序主要的结构特点是什么?来自<单片机的c语言应用程序设计>第... -
寇要司13457387893 ______ C语言的特点 1. 简洁紧凑、灵活方便 C语言一共只有32个关键字,9种控制语句,程序书写自由,主要用小写字母表示.它把高级语言的基本结构和语句与低级语言的实用性结合起来. C 语言可以象汇编语言一样对位、字节和地址进行操作, ...

蒲国券4009C语言中有哪些存储类型? -
寇要司13457387893 ______ c语言中的存储类型有auto, extern, register, static 这四种,存储类型说明了该变量要在进程的哪一个段中分配内存空间,可以为变量分配内存存储空间的有数据区、BBS区、栈区、堆区. 1. auto存储类型 auto只能用来标识局部变量的存储类型...

蒲国券4009C语言中三种基本结构的异同点是什么?
寇要司13457387893 ______ 通常的计算机程序总是由若干条语句组成,从执行方式上看,从第一条语句到最后一条语句完全按顺序执行,是简单的顺序结构;若在程序执行过程当中,根据用户的输入或中间结果去执行若干不同的任务则为选择结构;如果在程序的某处,...

蒲国券4009什么是C语言..? C语言有一些什么类型? -
寇要司13457387893 ______ C语言简介 什么是C语言 C语言是目前世界上流行、使用最广泛的高级程序设计语言. C语言对操作系统和系统使用程序以及需要对硬件进行操作的场合,用C语言明显优于其它高级语言,许多大型应用软件都是用C语言编写的. C语言具有绘...

蒲国券4009C程序的基本结构是怎样的?
寇要司13457387893 ______ C程序的基本结构 通常一个C程序包括一个或多个函数,其中必有一个main函数,称为主函数.C函数的定义主要分两部分:函数说明部分和函数体.其中函数体由C语言的语句序列组成,实现函数的功能.C程序总是从主函数开始执行.

蒲国券4009C语言中用于结构化程序设计的三种基本结构是? -
寇要司13457387893 ______ 顺序结构、选择结构、循环结构.顺序结构的程序设计是最简单的,只要按照解决问题的顺序写出相应的语句就行,它的执行顺序是自上而下,依次执行.选择结构用于判断给定的条件,根据判断的结果判断某些条件,根据判断的结果来控制程序的流程.循环结构可以减少源程序重复书写的工作量,用来描述重复执行某段算法的问题,这是程序设计中最能发挥计算机特长的程序结构 .循环结构可以看成是一个条件判断语句和一个向回转向语句的组合.

(编辑:自媒体)
关于我们 | 客户服务 | 服务条款 | 联系我们 | 免责声明 | 网站地图 @ 白云都 2024