梦见锡安
msgbartop
小舟从此逝,江海寄余生。
msgbarbottom

内存管理相关函数 | 2006年12月16日

1、经典的C动态内存管理相关函数

标准C提供了malloc, calloc, realloc, free等基于内存堆的管理函数,负责分配可用内存以及释放用过的内存。这些函数本身只负责告诉调用程序,当前有你想要size大小的可用内存块,它的首地址是xxxxx,并不会检查指针的使用是否越过了这个size或者说是offset,这个需要程序员自己去检查。

1
2
3
#include <stdlib.h>
 
void *malloc(size_t size);

malloc的作用分配一块大小为size个字节的可用内存块,并返回首地址。不能分配的时候返回NULL。

1
2
3
#include <stdlib.h>
 
void calloc(size_t nmemb, size_t size);

calloc的作用是分配并初始化内存块,返回一个指向nmemb块数组的指针,每块大小为size个字节。它和malloc的主要不同之处是会初始化(清零)分配到的内存。

1
2
3
#include <stdlib.h>
 
void *realloc(void *ptr, size_t size);

reallocptr所指地址为首址,分配size个字节的内存,并返回ptr所指地址。realloc不会初始化分配到的内存块,如果ptr为NULL则相当于malloc,如果size为NULL则相当于free(ptr)。不能分配返回NULL。

1
2
3
#include <stdlib.h>
 
void free(void *ptr);

free清除ptr所指向的地址,它只作清除的工作,并告诉系统,这块地址已经被释放和清除,可以重新被分配。

一个带bug的程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*
 * mallocfree.c - try to access illegally an address has wrong allocated
 */
 
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
 
int main(void)
{
        char *ptr = malloc(sizeof(char) * 5);
        strcpy(ptr, "123456789");
        printf("ptr : %sn", ptr);
        printf("freeing ptrn");
        free(ptr);
        sleep(1);
        printf("ptr : %sn", ptr);
        printf("trying to write the address has freedn");
        strcpy(ptr, "54321");
        sleep(1);
        printf("ptr : %sn", ptr);
        return 0;
}

sleep函数在里面是为了让肉眼更直观的分析程序的运行。执行make mallocfree,生成可执行文件,并运行之:

$ ./mallocfree
ptr : 123456789
freeing ptr
ptr :
trying to write the address has freed
ptr : 54321

在这里,ptr使用的地址已经越过了malloc分配给它的界限,而且指针在释放以后继续使用,这导致缓冲区溢出的隐患。

[更多...]


Linux采用FHS标准作为自己文件系统结构,以“/”为根目录,其它的文件系统都可以作为“/”下面的一级子目录来挂载(mount(1))。常见的文件系统有:

/boot:启动时加载内核所需的文件;

/bin:shell最基本的命令,命名来自binary二进制文件,但是一般也包含了各种可执行脚本文件;

/sbin:shell最基本的系统工具;

/dev:计算机各种设备文件目录;

/etc:各类软件的配置文件;

/etc/init.d:内核加载后需要执行的守护进程,作为运行级别做符号链接时的源;

/etc/X11:X Window系统的基本配置文件;

/lib:内核模块以及各类最基本的库,包括libc,libutil等等;

/mnt:其它文件系统的挂载点,例如vfat等文件系统一般都挂载在这个目录下;

/root:超级用户的主目录;

/var:可变数据的顶级目录;

/var/log:系统与应用程序的日志;

/var/lib:应用程序的各类可变的状态数据,例如数据库,cvs的配置等;

/var/mail:用户的邮箱;

/opt:附加的应用程序,例如那种打包为tar.gz,解压就可以运行的软件,一般放到这个下面;

/tmp:系统运行过程中产生的各类临时文件;

/home:用户主目录一般被挂载到这个目录下面;

/usr:Unix系统资源(Unix Sytem Resource)的缩写,用于用户共享数据,一般为静态数据,设置为只读不会影响系统运行;

/usr/bin:各类用户应用程序的基本路径;

/usr/sbin:各类用户实用工具的基本路径;

/usr/lib:各类应用程序所需的库以及编程库;

/usr/include:用于开发的各类C头文件;

/usr/local:本地使用的各类程序等,不会受系统升级影响;

/usr/src:源代码放置于此目录下;

/usr/share:共享的各类软件配置数据;

/usr/share/doc:用户手册的根目录;

/usr/X11R6:X Window系统的基本可执行文件与库

/proc:数据存在内存中的虚拟文件系统,系统信息,大部分为纯文本文件,包含了系统运行过程中各类的状态信息:

  • cpuinfo:系统CPU的信息,包括各类参数。
  • cmdline:加载内核时使用的命令行;
  • uptime:系统加载后流逝的秒数,以及其中CPU处于空闲状态的秒数;
  • version:内核版本的各种信息,包括编译的时间与源代码被编译的次数等等;
  • filesystems:可挂载的文件系统类型,第一列显示nodev表示当前机器硬件上不存在此文件系统;
  • devices:各类字符设备和块设备的主设备号和设备名称;
  • kcore:以core形式保存在硬盘上的物理内存,可以供gdb分析;
  • ioports:各类硬件设备驱动程序登记的I/O地址范围;
  • interrupts:保留的中断,包括中断号、中断发生的次数,使用这个中断的驱动等;
  • kmsg:printk生成的内核消息,可以用kmesg来检索它;
  • swaps:交换分区的信息;
  • mounts:当前加载的文件系统各类信息和参数;
  • partitions:当前硬件上的分区信息;
  • stats:cpu利用情况、内存页的情况、内存交换情况、进程运行和阻塞的情况、系统boot后相对UNIX经典时间(1970-01-01 GMT)流逝的秒数等;
  • driver/:驱动信息的目录;
  • net/:联网环境的信息,包括arp表、路由表、tcp的socket表、IGMP多播表、netstat的流量、各类交换数据等等;
  • sys/:系统参数的目录,可以用于调整系统的性能;
  • 数字起头的目录:系统当前各进程自己的状态信息,包括该线程的打开的文件描述符目录fd、环境变量environ、内存映像mem、根文件系统目录root、当前执行的命令exe、相关的进程信息statstatus等等。
  • self:到当前shell所在进程号目录的符号链接。