C++研究笔记(2)程序行为

本文探讨了C++程序中的不确定行为,包括未定义、未指定、由实现定义和特定于本地的行为。C++标准对这些行为进行了分类,并强调了完备的程序与错误构造之间的区别。理解这些概念对于编写健壮的C++代码至关重要。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数学概念上来讲,现代计算机就是“万能图灵机”的一个具体实现。从哲学上来说,以二进制逻辑运算为基础的计算机,其行为必然是确定的。“对于一个确定的输入,其输出是完全确定的。”哲学家和科幻小说作家们统一的观点是:无论如何,如果不为计算机的基础计算模型引入不确定性,人工智能(AI)不可能真正实现。但是,向一切其他问题一样,当我们换个角度考虑“计算机行为的确定性问题”的时候,会得出不同的结论。

通常当我们仅仅掌握一个系统(是系统论的哲学概念,不是某个计算机软件或硬件系统)的部分信息的时候,这个子系统的边界同样是不确定的。现代计算机通常由大量不同的部分组成,每一个部分都是前述的这类子系统,它们的边界是松散的,仅仅是一个大致类型的边界的约定。举一个例子:比如我们可以通过某个功能取得一块确定大小内存,但我们不可能事先知道得到的内存内保存的具体内容。

另一方面,作为“高级程序设计语言”,其对机器底层的表达能力还是有相当的差距的,尤其当某个语言要保持某个概念的“语义”时。语言通过语义表达的概念,是面向程序员的一种抽象,通常没有直接对应的机器底层机制,而是通过比较复杂的机器行为组合来模拟。语言抽象语义与机器底层机制的断层,就会造成另一种形式的不确定性。

最后,我们要认识到语言本身的社会性。语言的发展过程中,通常会有许多不同的实现给出不同的行为。作为 C++ 语言的特例,它还包括许多从 C 语言的各种实现版本遗传来的历史问题。对于这类不同编译器会给出不同解释和行为的概念,C++ 标准的策略是保留它们到特定的编译器来实现,标准中仅仅给出可能的 C++ 实现的行为选择。

这些不确定性自然会被带到我们写的程序中。

C++ 语言支持的一些默认行为,还有可能与机器配置的地理文化环境有关。比如语言文字,时区,地区习惯等等都会影响 C++ 提供的库的相关行为。这些行为对程序来说通常并不是真正不确定的。程序员要编写国际化/本地化的程序,总是要与这些信息打交道的。

C++ 标准明确定义:

1.3.14 well-formed program [defns.well.formed]

a C++ program constructed according to the syntax rules, diagnosable semantic rules, and the One Definition Rule (3.2).
完备的 C++ 程序”遵循 C++ 的语法规则,可诊断的语义规则,以及“一次定义原则(ODR)”。

1.3.4 ill-formed program [defns.ill.formed]

input to a C++ implementation that is not a well-formed program (1.3.14).
对于 C++ 实现来说,“病态的 C++ 程序”就是除了“完备的 C++ 程序”之外的文本输入。

1.3.12 undefined behavior [defns.undefined]

behavior, such as might arise upon use of an erroneous program construct or erroneous data, for which this International Standard imposes no requirements. Undefined behavior may also be expected when this International Standard omits the description of any explicit definition of behavior. [Note: permissible undefined behavior ranges from ignoring the situation completely with unpredictable result, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message). Many erroneous program constructs do not engender undefined behavior; they are required to be diagnosed. ]
错误的程序构造和数据会导致“未定义行为”,这些程序构造和数据本标准并未制定规范。当 C++ 标准遗漏对任何具有明显定义的行为进行描述时,也导致“未定义行为”。【注:可取的未定义行为包括完全忽略产生不确定结果的情况,或者在编译或程序执行时产生环境特有的,有文档描述的行为(可能同时发布出诊断消息),或者直接终止编译或执行(并发布诊断消息)。许多错误的程序构造不会造成未定义行为,这样的程序就需要被诊断。】

1.3.13 unspecified behavior [defns.unspecified]

behavior, for a well-formed program construct and correct data, that depends on the implementation. The implementation is not required to document which behavior occurs. [Note: usually, the range of possible behaviors is delineated by this International Standard. ]
由完备的程序构造和正确的数据产生的某些随实现而定的行为,被称为“未指明的行为”。C++ 实现并不需要提供这些行为的文档。【注:C++标准通常会列出行为可能的范围。】

1.3.5 implementation-defined behavior [defns.impl.defined]

behavior, for a well-formed program construct and correct data, that depends on the implementation and that each implementation shall document.
由完备的程序构造和正确的数据产生的某些随实现而定的行为,被称为“由实现定义的行为”,C++ 标准要求每个实现都对这些行为提供文档说明。

1.3.7 locale-specific behavior [defns.locale.specific]

behavior that depends on local conventions of nationality, culture, and language that each implementation shall document.
依赖于当地国别,文化和语言习惯的行为,被称为“特定于现场的行为”,C++ 标准要求每个实现都对这些行为提供文档说明。

C++ 的初学者经常会问一些貌似“专业”的问题,比如
    int i = 5;
    int j = (++i) + (++i) + (++i);

    int f(int a, int b);
    int i = 5;
    f(++i, ++i);
这样的问题实在不需要多做考虑,而且应该在实际编程实践中尽量避免。因为它们几乎都是“未指明的行为”或“由实现定义的行为”。另一方面,程序的错误或Bugs,通常是由于“未定义的行为”。

在安全网上逛的时候,突然发现一篇很好的文章!详细阐述了当前流行的api hook技术,rootkit技术和主动防御技术,涉及到深入的操作系统知识,需要一定的功底才能看懂,真的很不错,可以说是一篇难得的教程!现摘选如下: 一. 黑匣子的原理 对于一般用户而言,一个程序从开始运行直到结束,这期间内都做过什么,并不是我们需要关心的事情,他们只要听到播放器里的音乐、看到电影画面、和远方的朋友用通讯工具聊天就可以了,有谁会去关心从用户点击播放器程序图标到音乐响起的时间里,这个程序具体做了什么事情呢?然而,如果面对的程序是恶意软件之流,用户就不得不关心一下它到底对自己的计算机造成什么影响了。 程序在运行期间所进行的操作被称为“程序行为”(Action),一般泛程序进行的相对表现较明显的操作,例如创建读写文件、访问注册表、连接网络等,而在这些操作之外做的程序内部运算、判断、逻辑等操作并不是我们需要关心的,除非是对它进行复杂的分析如逆向工程。对程序行为进行监视记录的过程就是“跟踪”(Tracing),如果要进一步深入,则要使用调试器(Debugger)环境进行汇编级的令分析,这就是“调试”(Debugging),也可视为更全面的跟踪,因为调试过程可观察到整个程序里的运算和每一步过程。 也许很多用户会觉得,这些复杂技术距离我们很远,甚至会想像为需要复杂设备和程序才能完成,其实,这些技术的应用范围,一直就在我们身边。如果你正在使用一款防毒产品,那么你系统里执行的程序就已经处于被记录行为的状态了;如果你使用HIPS产品,就会更强烈的感受到程序运行被监视着;如果你正在使用调试器,那就不用我说了吧…… 在Windows系统里,至少有三种技术可以实现程序行为的记录,甚至控制程序的某些行为,分别是“虚拟机”(VM)、“API钩子”(API Hooking)和“API跟踪”(API Tracing)。 应用广泛的虚拟机技术 经常提到的虚拟机技术有两种,一种是普遍应用上的虚拟机技术,它是通过软件模拟的具有完整硬件系统功能的、运行在一个完全隔离环境中的完整计算机系统,此类虚拟机的概念比较广泛,可以是一种使用软件模拟一个完整的计算机硬件环境技术如VMWare,也可以是介于硬件和编译程序之间的交互介质,如Java虚拟机等;另一种则是反病毒产品中使用的“通用解密器”技术,为了检测一些复杂或者代码加密的病毒,杀毒引擎必须让它运行起来以便自我暴露危险程序行为,但是如果病毒真的在用户计算机里运行了,就违背反病毒产品的初衷了,因此反病毒产品也采取了一种虚拟环境检测方法,这就是虚拟机技术,但是这个技术并非是为病毒提供一套计算机仿真系统,这样就太庞大复杂和消耗资源了,这种虚拟机是杀毒引擎模拟出一个仿真CPU,这个“CPU”具备和真正CPU等同的令分析功能,杀毒引擎将待检测的程序代码读入“CPU”中逐条令循环执行,直到出现特定情况才结束工作,在这个过程中探知程序是否具备病毒行为特征或者暴露出病毒特征码。这就是杀毒引擎的“虚拟机技术”,它的目的就是让程序文件在没有实际运行的情况下得到运行后的结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值