一些知识点

本文深入解析了库函数与系统调用的区别与联系,详细解释了Linux下ls-al命令的输出含义,介绍了Linux进程的类型,并对C语言中的内存分配方式及常见错误进行了全面的讲解。

库函数与系统调用的联系与区别

这里写图片描述

一般而言,跟内核功能与操作系统特性紧密相关的服务,由系统调用提供;
具有共通特性的功能一般需要较好的平台移植性,故而由库函数提供。

库函数与系统调用在功能上相互补充,如进程间通信资源的管理,进程控制等功能与平台特性和内核息息相关,必须由系统调用来实现。


ls -al每一列的意思

ls -al
查看文件信息
drwx——+ 9 zyu staff 306 8 19 21:15 Pictures
drwxr-xr-x+ 6 zyu staff 204 3 30 22:09 Public

第一列:文件的类型与权限
第一个字母代表文件类型:d目录,-文件,l链接文件,b设备文件里的可供存储的接口设备,c表示设备文件里的串行端口设备,如键盘鼠标等一次性读取设备
接下来三个一组,第一组为文件所有者权限,第二组为同用户组的权限,第三组为其他非本用户组的权限
第二列:有多少文件名连接到此节点(i-node)
每个文件都会将它的权限与属性记录到文件系统的i-node中,不过我们使用的目录树却是使用文件名来记录,因此每个文件名就会连接到一个i-node,这个属性记录的就是有多少不同的文件名连接到相同的一个i-node号码
第三列:所有者账号
第四列:文件所属用户组
第五列:容量大小,默认单位B
第六列:创建或最近修改日期
查看完整时间 ls -l –full-time
第七列:文件名


Linux操作系统的进程类型

针对用户进程,又可以分为交互进程、批处理进程和守护进程三类。
(1) 交互进程:由一个shell终端启动的进程,在执行过程中,需要与用户进行交互操作,可以运行于前台,也可以运行在后台。
(2) 批处理进程:该进程是一个进程集合,负责按顺序启动其他的进程。
(3) 守护进程:守护进程是一直运行的一种进程,经常在linux系统启动时启动,在系统关闭时终止。它们独立于控制终端并且周期性的执行某种任务或等待处理某些发生的事件。例如httpd进程,一直处于运行状态,等待用户的访问。还有经常用的crond进程,这个进程类似与windows的计划任务,可以周期性的执行用户设定的某些任务。


C语言中的内存分配方式及常见错误

内存分配方式

首先看一下内存分配方式有哪些,一般来说有以下三种:
(1)从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量等等。
(2)在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。
(3)从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。这种方式可能引起的问题是比较多的。

常见的内存错误
发生内存错误是件非常麻烦的事情。编译器不能自动发现这些错误,通常是在程序运行时才能捕捉到。

常见的内存错误及其对策如下:
1、内存分配未成功,却使用了它。
解决办法是,在使用内存之前检查指针是否为NULL。如果指针p是函数的参数,那么在函数的入口处用assert(p!=NULL)进行检查。如果是用malloc或new来申请内存,应该用if(p==NULL) 或if(p!=NULL)进行防错处理。

2、内存分配虽然成功,但是尚未初始化就引用它。
犯这种错误主要有两个起因:一是没有初始化的观念;二是误以为内存的缺省初值全为零,导致引用初值错误(例如数组)。
内存的缺省初值究竟是什么并没有统一的标准,尽管有些时候为零值,但这点在不同的编译器上会有不同的实现。所以好的做法,是手动给数组赋上初值。

3、内存分配成功并且已经初始化,但操作越过了内存的边界。
例如在使用数组时经常发生下标“多1”或者“少1”的操作。特别是在for循环语句中,循环次数很容易搞错,导致数组操作越界。

4、忘记了释放内存,造成内存泄露。
含有这种错误的函数每被调用一次就丢失一块内存。刚开始时系统的内存充足,你看不到错误。终有一次程序突然死掉,系统出现提示:内存耗尽。
动态内存的申请与释放必须配对,程序中malloc与free的使用次数一定要相同,否则肯定有错误(new/delete同理)。
5、释放了内存却继续使用它。
有三种情况:
(1)程序中的对象调用关系过于复杂,实在难以搞清楚某个对象究竟是否已经释放了内存,此时应该重新设计数据结构,从根本上解决对象管理的混乱局面。
(2)函数的return语句写错了,注意不要返回指向“栈内存”的“指针”或者“引用”,因为该内存在函数体结束时被自动销毁。
(3)使用free或delete释放了内存后,没有将指针设置为NULL。导致产生“野指针”。


什么是野指针和内存泄漏?如何避免野指针

内存泄漏:①访问已经释放的内存
②访问没有权限的内存

野指针:指向内存被释放的内存或者没有访问权限的内存的指针。

“野指针”的成因主要有3种:
(1)指针变量没有被初始化。任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。例如

char *p = NULL;
char *str = new char(100);

(2)指针p被free或者delete之后,没有置为NULL。

(3)指针操作超越了变量的作用范围。这种情况让人防不胜防,示例程序如下:

class A 
{ 
public:
    void Func(void)
    { 
        cout << “Func of class A” << endl; 
    }
};

void Test(void)
{
     A  *p;
     if(...)
     {
        A  a;
        p = &a; // 注意 a 的生命期
     }
     p->Func(); // p是“野指针”
}

如何避免野指针:
一、对指针进行初始化
①将指针初始化为NULL。
char * p = NULL;

②用malloc分配内存
char * p = (char * )malloc(sizeof(char));

③用已有合法的可访问的内存地址对指针初始化
char num[ 30] = {0};
char *p = num;

二、指针用完后释放内存,将指针赋NULL。
delete(p);
p = NULL;

注:
malloc函数分配完内存后需注意:
①检查是否分配成功(若分配成功,返回内存的首地址;分配不成功,返回NULL。可以通过if语句来判断)

②清空内存中的数据(malloc分配的空间里可能存在垃圾值,用memset或bzero 函数清空内存)
void bzero(void *s, int n);

s是 需要置零的空间的起始地址; n是 要置零的数据字节个数。

void memset(void *start, int value, int size);

如果要清空空间的首地址为p,value为值,size为字节数。


分别写出BOOL,int,float,指针类型的 变量a与零相比的语句

BOOL : if ( !a ) or if(a)

int : if ( a == 0)

float : const EXPRESSION EXP = 0.000001
if ( a < EXP && a >-EXP)

pointer : if ( a != NULL) or if(a == NULL)


关于各种类型占字节数

这里写图片描述

总结:64位与32位只有long和*指针类型字节数不一样

特殊的: int c:16 表示占32位中的16位(4个字节是32位),即占2个字节
tips: 冒号后面的数小于类型的总字节数,即int c : n 中, 0 < n < 32


关于程序的内存分配问题

BSS段:(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文Block Started by Symbol的简称。BSS段属于静态内存分配。

数据段 :数据段(data segment)通常是指用来存放程序中 已初始化 的 全局变量 的一块内存区域。数据段属于静态内存分配。

代码段: 代码段(code segment/text segment)通常是指用来存放 程序执行代码 的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于 只读 , 某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些 只读的常数变量 ,例如字符串常量等。程序段为程序代码在内存中的映射.一个程序可以在内存中多有个副本.

堆(heap) :堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc/free等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张)/释放的内存从堆中被剔除(堆被缩减)

栈(stack) :栈又称堆栈, 存放程序的 局部变量 (但不包括static声明的变量, static 意味着 在数据段中 存放变量)。除此以外,在函数被调用时,栈用来传递参数和返回值。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。储动态内存分配,需要程序员手工分配,手工释放
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值