《c专家编程:对内存的思考 》笔记

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zztingfeng/article/details/82914133

1、Intel 80X86系列处理器的发展历程

4008 —> 8008  —> 8080  —> 8085  —> 8086  —> 80186  —> 80286  —> 80386  —> 80486  —> Pentium 32

 

2、内存模型以及它的工作原理

      段的含义:一块64KB的内存区域,有一个段寄存器所指向。

      内存地址的形成:取得寄存器的值,左移4位(相当于乘以16,左乘右除),或者把段寄存器值看成20位,在值得右边扩充4个0,然后段寄存器值加上偏移的16位地址,得到最终的值。

 

3、虚拟内存

       概念:只是对多层存储进行扩充,使用磁盘而不是主存来保存运行进程的映像。

       虚拟内存通过“页的形式组织。页就是操作系统在磁盘和内存之间移来移去或进行保护的单位。,一般为几K字节。

      进程只能操作位于物理内存的页面中。

 

4、Cache存储器

       Cache位于CPU和内存之间,是一种极快的存储缓冲区,是多层存储概念的更深扩展。

       Cache包含一个地址的列表以及他们的内容。

 

5、数据段和堆

       数据段能够根据需要自动增长的包含了一个对象,这个对象就是堆。

      堆区域用于动态分配的存储且堆中的所有东西都是匿名的,不能按名字直接分配,只能通过指针间接访问。

      对内存的回收不必与他所分配的顺序一致。

      堆的末端由一个称为break的指针来标识,但堆管理器需要更多的内存时,它可以通过系统调用brk和sbrk来移动break指针。

      内存管理的调用:malloc和free:从堆中获得内存以及吧内存返回给堆。brk和sbrk:调整数据段的大小至一个绝对值(通过某个增量)。

 

6、内存泄漏

      堆常会产生两种内存的问题:释放或改写正在使用的内存(称为内存毁坏);未释放不再使用的内存(称为内存泄漏)。

      避免内存泄漏:每次调用malloc函数时,在以后都要调用相应的free来释放它。

       使用alloca来分配动态内存,当离开调用的alloca的函数时,他所分配的内存会自动释放。

       泄露的内存往往比忘记释放的数据更大。

       检测内存泄漏的方法:使用swap命令来观察还有多少可用的交换空间,用“ps-lu用户名”命令来显示所有进程的大小,确定可疑的进程。

 

7、总线错误和段错误

       总线错误和段错误在不同的操作系统版本上各有不同。

       总线错误:总线错误几乎都是由于未对齐的读或写引起的。

        对齐:数据项只能存储在地址是数据项大小的整数倍的内存位置上。编译器通过自动分配和填充数据来进行对齐。

8、段错误

       段错误是由内存管理单元的异常所引起的,该异常通常由于解除引用一个未初始化或非法值的和指针引起的。

      如果未初始化的指针恰好具有未对齐的值,他将产生总线错误,而不是段错误。

   导致段错误的原因

       A、解除引用一个包含非法值的指针。

       B、解除引用一个空指针(常常由于从系统程序中返回空指针,并未检查就引用)。

       C、在未得到正确的权限是进行访问。(例如试图往一个只读的文本段存储值)

       D、用完了堆栈或堆空间。

9、可能导致段错误的常见编程错误

      坏指针值错误。

    在指针赋值之前就用它来引用内存。

    向库函数传送一个坏指针。

    对指针释放之后在访问它的内容。

     改写错误

    越过数组边界写入数据。

    在动态分配的内存两端之外写入数据。

    改写一些堆管理数据结构。(在动态分配的内存之前的区域写入数据)

    指针释放引起的错误

    释放同一个内存块两次。

    释放一块未曾使用malloc分配的内存。

    释放乃在使用中的内存。

    释放一个无效指针。

猜你喜欢

转载自blog.csdn.net/zztingfeng/article/details/82914133