回顾
gcc 概述
c语言的开发相关文件
- .c 源文件
- .o 目标文件
- .h 头文件
- .a 静态库
- .so 共享库文件
环境变量
- PATH/CPATH/LD_LIBRARY_PATH/
静态库和共享库
动态调用函数(dl系列函数)
- dlopen 从硬盘打开共享库文件
- dlsym 从共享库文件中打开函数
- dlclose 关闭共享库文件
- dlerror 判定错误
今天
C语言的错误处理
环境表(程序中如何拿到环境变量)
Unix/Linux内存管理
ldconfig
/lib
/usr/lib
/etc/ld.so.conf 需要root权限,如没权限,使用LD_LIBRARY_PATH
ldd libmy.so 列出共享库的依赖关系
错误处理
C程序员错误的处理都是通过返回值体现,方式如下:
- a 返回指针类型的函数,用NULL代表错误(fopen/malloc)
- b 返回int类型的函数,如果返回的数据不可能是-1 可以用-1 代表错误,非负数代表 正常的返回。
- c 返回int类型的函数,如果返回的数据有可能是-1,用指针把数据带回,同时用返回值-1代表错误,返回0代表正确。
- d 如果函数不需要错误处理,可以把返回值写成void。
有以下几个函数,分析一下错误的处理方式
1 比较两个整数,返回最大值 c
2 生成0-9的随机数 随机到0视为错误 b (time/srand/rand)
3 随便返回字符串 a
4 打印一个字符串 d
官方错误处量
C语言对于错误的处理提供了变量和函数:
C把错误都做成了编号,用外部全局变量errno
存储。
错误的信息可以通过编号显示
函数:
- strerror
- perror - 最常用
- printf("%m")
说明
调用C库函数/Unix系统函数时,如果正确,不改变errno,但如果有错误,把错误的编号放入errno中。(不是所有的函数都使用errno)。
不能使用errno判断是否出错,errno只是记录出了什么错
环境表
全局变量environ存储了环境表,环境表是一个字符指针数组(字符串数组),environ就是这个数组的首地址。(char **
)
环境表有一些操作的函数,包括 setenv/putenv/unsetenv/getenv/clearenv(慎用,清空) 等。
内存管理
STL -> 内存自动分配和回收
|
C++ -> new分配 delete回收 ----- allocator内存分配器 强数据类型
|
C语言 -> malloc/free ---- void*
|
Linux/Unix 系统函数(System call) -> sbrk/brk(都可以分配和回收内存)
|
Linux/Unix 系统调用 -> mmap/munmap 内存映射
| 用户层
|=======================================================
| 内核层(了解)
内核层系统调用 kmalloc/vmalloc/get_free_page …
虚拟内存
2的10次方 1KB
2的20次方 1MB
2的30次方 1GB
每个进程都有0-4G的虚拟内存地址空间,但虚拟内存地址只是一个数字,并不能存任何的东西,必须映射到物理内存/文件上才能真正的存储数据。
其中
- 0G-3G是用户使用,叫用户空间
- 3G-4G是内核使用,叫内核空间
用户层的代码只能访问用户空间,无法直接访问内核空间。Unix/Linux系统提供了能进入内核空间的函数,叫系统调用。
Unix/Linux在管理内存时,以内存页作为最小单位。一个内存页就是4k(4096字节),内存的分配和回收都是内存页作为基本单位。
关于段错误
有以下几种可能:
1 虚拟内存地址没有映射到物理内存
2 做一些没有权限的内存操作(比如:修改只读区)
进程和程序(内存和硬盘)
程序 就是 代码 编译连接之后 保存在硬盘上的可执行文件
进程 就是 运行起来的程序,也就是把 文件加载到内存中
进程的内存空间
每个进程的内存是分区/段的,包括:
- 1-代码区 : 存放函数中的代码,函数指针就是指向代码区
代码区 是 只读区 - 2-全局区(数据段) : 存放全局变量 / static 的变量也在全局区
全局区在主函数执行之前分配空间 - 3-BSS段:存放未初始化的全局变量
BSS段在主函数执行前自动清0 - 4-堆区 : 也叫自由区,程序员可管理的区域,malloc/free
字符串字面值(字符串常量) 存在接近代码区的区域,也是只读的。 - 5-栈区 : 存放局部变量,包括函数的参数
栈区的内存分配和回收是自动完成的