堆与栈(Heap and Stack)

堆相对比较容易理解, 就是计算机剩余的内存, 可以通过 malloc 函数访问获取堆内存。 每次调用 malloc , 操作系统使用内部函数为你注册分配一块内存, 并返回指向它的指针。 当你使用完之后, 要用 free 函数将它返回给操作系统以便其它程序可以使用。 如果没有这么做的话, 将会导致你的程序出现内存泄漏。

栈是一个特殊的内存区域, 存储函数创建的本地变量。 它的工作原理是每个函数的参数被压入堆栈,并在函数内使用。 这是真正的栈道数据结构, 后进先出。 对于本地变量也是相同的。 栈的好处是简单, 当函数退出时, C 编译器将这些变量推出栈道进行清理。 这样可以简单的避免栈道上的变量有内存泄漏。

如果变量不是用 malloc 直接获取, 也不是在函数内通过 malloc 间接获取, 那么这个变量就是在栈上。

堆栈需要注意的三个问题

  1. 如果你在栈上用 malloc 获取了一块内存, 并将指针指向这块内存, 当函数退出时, 指针将会被推出栈道并丢失;
  2. 如果在栈上使用过量的数据(大型数据结构和数组), 将会出现栈溢出(StackOverflow)并导致程序退出。 在这种情况下, 应通过 malloc 使用堆内存;
  3. 如果在栈上将指针指向变量, 将它作为你函数的返回值, 那么接受返回值的函数将会出现段错误(Segmentation fault),因为指针指向的数据已经被出栈并被清理了, 指针指向了无效区域(Dead space)。

指针

指针的典型用法

  1. 向系统申请一块内存, 包括字符串以及结构体;
  2. 作为参数向函数传递大块内存,通过使用指针就不用传递整个内存块;
  3. 指针指向函数的地址作为进行动态回调;
  4. 负责扫描内存或文件,比如:将网络 Socket 数据流转换为复杂的结构或者分析文件

指针的语法

type * ptr // 定义一个名称为 ptr 的 type 类型的指针;
*prt // 指针 ptr 指向内容的值;
*(ptr + i) // 指针 (ptr + i) 指向内容的值
&thing // thing 的地址
type *ptr = &thing  // 将名称为 ptr 的 type 类型的指针指向 thing 的地址
ptr++ //将 ptr  指向的地址加一位