运行时的面向对象编程(OOP)与过程式编程对比

6

我有一个非常简单的问题,在互联网上找不到答案。

所以,我的问题是,在过程式编程中,代码位于代码段中,进入只读内存区域。变量要么在堆栈上,要么在堆上。

但是面向对象编程(OOP)表示对象在内存中创建。那么,这是否意味着函数甚至写入R / W内存区域?

并且,操作系统是否必须具有一些内置的OOP程序支持?例如,如果OS不允许在只读代码段之外读取指令。谢谢。


这取决于编程语言,更重要的是该语言的运行时。当前CLR可以在堆栈上创建对象(大多数情况下是值类型,除非被提升)。面向对象编程或“过程式”对于使用“数据段”没有固有的说法,但只读存储器在任何情况下都是只读的。结尾非常混乱,我甚至不确定如何回答。我认为问题在于试图将40个问题合并为一个。一次只关注一个问题。 - user166390
3个回答

6

通常,面向对象编程(OOP)和过程式编程都是存在于源代码级别的抽象概念。一旦程序被编译成可执行机器代码,这些抽象概念就不存在了。因此,一个特定的语言是OOP还是过程式对它使用的内存区域或指令执行位置没有影响。

操作系统本身通常不知道也不关心一个可执行文件是用OOP还是过程式语言编写的。它只关心该可执行文件使用二进制操作码与其本地指令集兼容,并且该可执行文件具有其可以理解的ABI(二进制接口)。


好的,但是,例如 MS Windows 允许您跳转到存储在 .data 区域中的函数吗?毕竟系统不知道它是一些数据还是指令。而且,也很有趣的是,为什么甚至程序代码也进入只读区域? - B.Gen.Jack.O.Neill
@B.Gen.Jack.O.Neill,这取决于架构。在历史上,执行存储在代码段之外的代码的能力一直被黑客利用。例如,大多数堆栈缓冲区溢出攻击基本上是试图执行放置在堆栈缓冲区中的shell代码。因此,某些硬件架构会在指令指针最终指向进程的代码段之外的地址时触发故障。 - Charles Salvia
只读代码段的原因是为了防止恶意注入代码。系统对于数据或可执行命令的概念并不比它知道你喜欢芝士汉堡还是披萨更多,只知道下一个操作是什么。这也是编译器可以创建可执行文件的原因之一。我认为你应该阅读一下冯·诺伊曼体系结构的相关资料。 - jcolebrand

3

这是一个好问题。

虽然对象理论上包含了“函数”和“数据”,但大多数实现将它们分开。代码被拆分并存储在RO段中,而RW区域中的对象则有一种方式可以引用RO区域中的代码。代码和数据的耦合仅由人类程序员和类型检查器在概念上使用,以确保您不违反规则和原则。

像Java/C#这样的语言通常会使每个对象具有标识对象类型的“标签”。对象本身只是一个按预定顺序排列所有字段的结构体。该标记可以用于查找RO区域中要调用的函数。RO区域中的函数被修改为添加一个额外的参数,称为“this”或“self”,通过该参数可以访问所述对象的内容。当方法需要引用字段时,它知道预先指定的顺序,因此可以正确地执行操作。请注意,需要一些技巧来解决继承问题,但这是想法的核心。

Python/Ruby这样的语言通常会使对象成为哈希表,在编译语言而不是通过字节码解释器运行的情况下,方法是指向RO区域中的代码的指针。通过查找哈希表内容并跟随代码指针进行函数调用。字段也在同一哈希表中查找。

有了这些基础知识,大多数实现会使用技巧来避免跟随指针查找要调用的函数的部分。他们试图找出并缩小可能的调用范围到一个单一的函数。然后,他们可以将查找替换为直接调用正确的函数,这是一种更快的解决方案。

简而言之,语言“语义”将字段和方法视为对象的一部分。“实现”将它们分成RO和RW段。因此不需要操作系统支持。


1

OOP并没有这样说。我不知道你在哪里读到的,如果你能加上引用那会更好。

对象变量,所以你对变量的了解也适用于对象。在像C#(实际上是.net框架)这样的语言中,对象只能存储在堆中,因为它们被称为引用类型。在C++中,它们可以存在任何地方。

但是OOP说对象是在内存中创建的。那么,这是否意味着函数甚至也写入R/W内存区域?

从这个问题中,我得出结论,你认为函数是对象。这在远非每种OOP语言中都是正确的。这来自于函数式语言,其中函数是一等公民对象。函数在大多数情况下是不可变的,并且放置在只读部分。

常见的操作系统如Windows、Linux和MacOsx并不知道对象。这纯粹是程序概念。.net框架和Java虚拟机提供了抽象层。它们是具有内置对象支持的执行环境。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接