Rust的胖指针到底胖在栈上还是堆上,objdump( 二 )


细究这两个概念的区别并不是本文的重点,所以这里粗略的对“浅拷贝”和“深拷贝”做如下区分,对于把变量 a 拷贝给 b:如果拷贝后,b 的内容完全等于 a,并且两个变量在内存中是独立的,则称此次拷贝为“深拷贝” 。如果靠背后,只是通过 b 能够访问 a 中的内容,a 的内容改变时,b 的“内容”也随之改变,则称此次拷贝为“浅拷贝” 。
这样看来,就本例而言,b = a;显然是一次“深拷贝”,因为 a,b 在内存中彼此独立,并且拷贝后,b 的内容和 a 的内容完全相同 。那C语言的结构体赋值拷贝一定是“深拷贝”吗?我们将结构体 s 新增一个指针成员 buf:对 a 的初始化也做相应修改,相关C语言代码如下,请看:为了讨论主题,上述C语言代码没有做错误处理 。
现在 b = a; 还是“深拷贝”吗?读者如果做了实验,应该会发现,b 的 buf 成员本身在内存中的确独立于 a 的 buf 成员,但是它指向的内存却与 a 的 buf 成员指向的内存是同一块,所以这时 b = a; 不再是纯粹的“深拷贝”了 。小结本节主要讨论了C语言结构体的赋值语法可以用于拷贝,并针对之前读者的几个典型问题做了较为详细的实例探讨 。
不过,C语言是一门非常灵活的编程语言,可能同样的一条语句,在不同的环境下执行结果是不一样的,这一点本文最后的讨论就是一个实例 。应该明白,本文举的例子仅是为了抛砖引玉,展示遇到问题该如何分析的方法,学习C语言,应该乐于做实验尝试才对 。欢迎在评论区一起讨论,质疑 。文章都是手打原创,每天最浅显的介绍C语言、linux等嵌入式开发,喜欢我的文章就关注一波吧,可以看到最新更新和之前的文章哦 。
c语言程序经过编译后,每条指令都有一个内存地址,那两个程序如果有相同内存地址的指令怎么办?
【Rust的胖指针到底胖在栈上还是堆上,objdump】

Rust的胖指针到底胖在栈上还是堆上,objdump


把一个程序自己的代码、数据、堆栈看成一块完整的砖头 。编译器就是造砖机,安排好这一块砖内部的结构 。裸奔的系统就这一块砖,不会发生相互覆盖的矛盾 。如果跑多任务,砖头就多了 。但这时通常会引入操作系统来管理砖头 。堆砌砖头时会给每块砖头不一样的起始坐标,确保不发生两块砖头占一个空间的情况 。早期的dos操作系统规定每块砖头高度不超过1M 。
编译器做出来的每块砖内部都是用偏移地址0000h—ffffh来区分单元,但是操作系统在往物理内存搬砖堆砌时,会给每块砖不同的段起始地址,和偏移地址加在一起才是物理地址 。这样就不会发生重叠了 。当然这里也有编译器的功劳 。编译器除了造砖,还会生成一个规格标签,用于通知操作系统这砖有多大多厚,让操作系统能好好堆砖不浪费空间 。
不同操作系统的这种规格标签格式不一样,因此windows程序是不能直接跑在linux下的 。后来的处理器出现了mmu,内存管理单元,程序的地址空间和物理地址空间的换算就更复杂了 。但是保证不同程序各自空间不发生覆盖还是基本要求 。一个程序能覆盖别的程序空间,大概是病毒恶意代码才做的事情 。cpu的安全特性越来越强,这种情况很少见了吧 。

推荐阅读