linux中 文件属性以 l、b、c、d。开头的都是什么文件?
l是链接,相当于windows的快捷方式
d是目录,相当于windows的文件夹
c是字符设备文件,给你说你不懂,鼠标,键盘算是
b是块设备,硬盘就是一个例子
/etc/services : 定义网络服务的端口
linux中 UID PID PPID 分别是什么?
UID是用户ID,
PID是进程ID,
PPID是父进程ID。
程序kill -9与kill -15的区别
在Linux/unix下,中止一个Java进程有两种方式,一种是kill -9 pid,一种是kill -15 pill(默认)。
两种方式的区别是:
SIGNKILL(9) 的效果是立即杀死进程. 该信号不能被阻塞, 处理和忽略。
SIGNTERM(15) 的效果是正常退出进程,退出前可以被阻塞或回调处理。并且它是Linux缺省的程序中断信号。
内存分配方式有几种?
静态存储区 栈 堆 的内存分配
1,从静态存储区域分配内存。(全局变量 static)程序编译的时候内存已经分配好了,并且在程序的整个运行期间都存在,例如全局变量。
2,在栈上创建。在执行函数时,函数内局部变量的存储单元可以在栈上创建,函数结束时这些存储单元自动被释放。
处理器的指定集中有关于栈内存的分配运算,因此效率比较高,但是分配的内存容量有限。
3,在堆上分配内存,亦称动态内存分配,程序在运行的时候用malloc函数或new运算符申请任意大小的内存,程序员要用free函数或delete运算符释放内存。动态内存使用非常灵活,但问题也很多。
常见的错误
类型 1:内存未分配成功,却使用了它。
方 法:在使用之前检查指针是否为NULL。
1)当指针p是函数的参数时,在函数入口处用语句assert(p!=NULL)进行断言检查。
2)当使用malloc或new来申请内存时,应该用if(p != NULL)进行防错检查。
类型 2:引用了尚未初始化的指针
原 因:内存的缺省初始值究竟是什么并没有统一的标准,在使用之前都进行初始化。
1)没有初始化的观念。
2)内存的缺省值是未定义,即垃圾值。
类型 3:越界操作内存
原 因:内存分配成功且初始了,但越界操作是不允许的。
例 如:在使用数组时经常发生下标“多1”或“少1”,特别是在for循环语句时。
类型 4:忘记释放内存,造成内存泄漏。
原 因:含有这种类型错误的函数,每被调用一次,就丢失一块内存。当内存充足时看不到这种错误带来的影响,当内存耗尽时系统提示:“内存耗尽”。因此,动态内存的申请与释放必须配对,程序中malloc与free的使用次数要相同。
类型 5:释放了内存却继续使用它
原 因:对应的情况有2种
1)返回了“栈内存的指针或引用”,因为堆栈中的变量在函数结束后自动销毁。
2)某块内存被free后,没有将指向该内存的指针设置为NULL,导致产生“野指针”
野指针
概念:“野指针”不是NULL指针,是指指向“垃圾”内存的指针。即指针指向的内容是不确定的。
指向不确定地址的指针变量
访问了没有权限的内存
访问了已经释放了的内存
产生的原因:1)指针变量没有初始化。因此,创建指针变量时,该变量要被置为NULL或者指向合法的内存单元。
2)指针p被free之后,没有置为NULL,让人误以为p是个合法的指针。
3)指针跨越合法范围操作。不要返回指向栈内存的指针或引用
例子1-1:引用尚未初始化的指针
[cpp] view plain copy
char *p;
*p = 'A';//error,p指向未定义
例子1-2:return语句返回指向“栈内存”的指针
[cpp] view plain copy
char *GetString1(void)
{
char p[] = "hello world!";
//p在栈区,常量字符串在常量字符区
return p;//error,返回栈内存的地址
}
例子1-3:使用了被释放的内存
[cpp] view plain copy
char *pstr = (char *)malloc(sizeof(char)*100);
free(pstr); //pstr所指的内存被释放
if (NULL !=pstr)//没起到作用
{
strcpy(pstr,"string!");//error,有时候程序不会提示有误,但还是不允许
}
注意:free()释放的是指针指向的内存!不是指针变量!这点非常非常重要!指针是一个变量,只有程序结束时才被销毁。释放了内存空间后,原来指向这块空间的指针还是存在!只不过现在指针指向的内容的垃圾,是未定义的,所以说是垃圾。因此,前面我已经说过了,释放内存后把指针指向NULL,防止指针在后面不小心又被解引用。
对比下面的例子,加深理解
例子1-4:函数返回值传递动态内存
[cpp] view plain copy
char* GetMemory(int num)
{
char *p = (char *)malloc(sizeof(char) * num);
return p ;//ok,返回堆区的地址值
}
例子1-5:
[cpp] view plain copy
char *GetString(void)
{
char *p = "hello world!";
//指针变量p在栈区,指向文字常量区的字符
return p;//ok,返回字符串的地址
}
避免的方法:
1.使用前对其初始化(置为null;用malloc分配内存,访问合法内存)
2.指针用完后记得释放内存(置为null, 用malloc的用free , 用memset清零内存)
写bool , float, 指针变量 与“零值”比较的if语句。
布尔变量与零值比较
l 【规则4-3-1】不可将布尔变量直接与TRUE、FALSE或者1、0进行比较。
根据布尔类型的语义,零值为“假”(记为FALSE),任何非零值都是“真”(记为TRUE)。TRUE的值究竟是什么并没有统一的标准。例如Visual C++ 将TRUE定义为1,而Visual Basic则将TRUE定义为-1。
假设布尔变量名字为flag,它与零值比较的标准if语句如下:
if (flag) // 表示flag为真
if (!flag) // 表示flag为假
其它的用法都属于不良风格,例如:
if (flag == TRUE)
if (flag == 1 )
if (flag == FALSE)
if (flag == 0)
4.3.2 整型变量与零值比较
l 【规则4-3-2】应当将整型变量用“==”或“!=”直接与0比较。
假设整型变量的名字为value,它与零值比较的标准if语句如下:
if (value == 0)
if (value != 0)
不可模仿布尔变量的风格而写成
if (value) // 会让人误解 value是布尔变量
if (!value)
4.3.3 浮点变量与零值比较
l 【规则4-3-3】不可将浮点变量用“==”或“!=”与任何数字比较。
千万要留意,无论是float还是double类型的变量,都有精度限制。所以一定要避免将浮点变量用“==”或“!=”与数字比较,应该设法转化成“> =”或“ <=”形式。
假设浮点变量的名字为x,应当将
if (x == 0.0) // 隐含错误的比较
转化为
if ((x> =-EPSINON) && (x <=EPSINON))
其中EPSINON是允许的误差(即精度)。
例如精度为:const float EPSINON = 0.00001;
4.3.4 指针变量与零值比较
l 【规则4-3-4】应当将指针变量用“==”或“!=”与NULL比较。
指针变量的零值是“空”(记为NULL)。尽管NULL的值与0相同,但是两者意义不同。假设指针变量的名字为p,它与零值比较的标准if语句如下:
if (p == NULL) // p与NULL显式比较,强调p是指针变量
if (p != NULL)
不要写成
if (p == 0) // 容易让人误解p是整型变量
if (p != 0)
或者
if (p) // 容易让人误解p是布尔变量
if (!p)
灭绝人性的智力题
三人决斗问题:
三个小伙子同时爱上了一个姑娘,为了决定他们谁能娶这个姑娘,他们决定用手枪进行一次决斗。阿历克斯的命中率是30%,克里斯比他好些,命中率是50%,最出色的枪手是鲍博,他从不失误,命中率是100%。由于这个显而易见的事实,为公平起见,他们决定按这样的顺序:阿历克斯先开枪,克里斯第二,鲍博最后。然后这样循环,直到他们只剩下一个人。那么这三个人中谁活下来的机会最大呢?他们都应该采取什么样的策略?
三人相对
A活下来有三种情况
1.A杀了C,B杀不死A,A又杀了B,概率30%×50%×0.3/0.65
2.A杀不死C,B杀了C,A杀了B,概率70%×50%×0.3/0.65
3.A杀不死C,B杀不死C,C杀了B,A杀了C,概率70%×50%×30%
所以A活下来的可能性为0.105+3/13≈0.336大于三分之一,比较幸运了。
B活下来有三种情况
1.A杀了C,B杀了A,概率30%×50%
2.A杀不死C,B杀了C,AB相对的情况下B杀了A,概率70%×50%×0.35/0.65
3.A杀了C,B杀不了A,AB相对的情况下B杀了A,概率30%×50%×0.35/0.65
所以B活下来的可能性为0.15+3.5/13≈0.419大于三分之一,非常幸运了。
C活下来只有一种情况
A杀不死C,B杀不死C,C杀了B,A杀不死C,C杀了A,概率70%×50%×70%
所以C活下来的可能性为0.245小于三分之一,非常不幸。
ABC活下来可能性之和恰为1。