《程序员面试宝典》基础知识点总结

笔者在2015年求职准备时,看《程序员面试宝典》一书,做的笔记。分享给大家,希望能有所帮助。

STL模板与容器

  1. 模板:类(及结构等各种数据类型和函数)的宏。有时叫做甜饼切割机,正规的名称应叫做泛型。一个类的模板叫做泛型类,而一个函数的模板也自然而然地被叫做泛型函数。
  2. 容器:可容纳一些数据的模板类。STL中有vector、set、map、multimap和deque等容器;
  3. 向量(Vector):基本数组模板,这是一个容器;
  4. 游标(Iterator):它是一个指针,用来指向STL容器中的元素,也可以指向其他的元素;
  5. 标准模板库是一个基于模板的容器类库,包括链表、列表、队列和堆栈;
  6. 容顺序器是包容其他对象的对象;
  7. 顺序容器可以提供对成员的顺序访问和随机访问。关联容器则经过优化关键值访问它们的元素;
  8. 任何对象如果是通过new操作符申请了空间,必须显示的调用delete来销毁这个对象;
  9. 局部变量,在main函数退出时,自动释放所占内存空间;
  10. 泛型编程是一种基于发现高效算法的最抽象表示的编程方法。也就是说,以算法为起点并寻找能使其工作且有效率工作的必要条件集。泛型编程假定有某些基本的法则在支配软件组件的行为,并且基于这些法则有可能设计可互操作的模块,甚至还有可以使用此法则去指导我们的软件设计。STL就是一个泛型编程的例子。C++是我可以实现令人信服的的例子的语言;
  11. 一个函数在编译时被分配给一个入口地址,这个入口地址就称为函数的指针;
  12. 函数指针的用途很多,最常用的用途之一是把指针作为参数传递到其他函数;

面向对象

  1. 面向对象设计的三原则:封装、继承、多态;
  2. 里氏代换原则是继承复用的基石:子类型必须能够替换它们的基类型;
  3. 开闭原则是面向对象设计的重要特性之一:软件对拓展应该是开放的,对修改应该是关闭的;
  4. 对于一个空类,编译器默认产生4个成员函数:默认构造函数、析构函数、拷贝构造函数和赋值函数;
  5. struct和class的区别:区别是class中变量默认是private,struct中变量默认是public;
  6. 必须使用静态变量在一个类的所有实例间共享数据。如果想限制对静态成员变量的访问,则必须把它们声明为保护型或私有型。不允许使用静态成员变量去存放某一个对象的数据。静态成员数据是在这个类的所有对象间共享的。
  7. 初始化列表的初始化变量顺序是根据成员变量的声明顺序来执行的;
  8. 常量必须在构造函数的初始化列表里面初始化或者将其设置成static;
  9. 将CObject的析构函数设为virtual型,则所有CObject类的派生类的析构函数都将自动变为virtual型,这保证了在任何情况下,不会出现由于析构函数未被调用而导致的内存泄露;
  10. 虚函数采用一种虚调用的办法。虚调用是一种可以在只有部分信息的情况下工作的机制,特别允许我们调用一个只知道接口而不知道其准确对象类型的函数。但是如果要创建一个对象,你势必要知道对象的准确类型,因此构造函数不能为虚;
  11. 一个const变量是不能随意转化成非const变量的;
  12. 用“+”赋值必须返回一个操作值已知的对象,除非它是一个const对象;
  13. 多态性可以简单的概括为“一个接口、多种方法”,在程序运行的过程中才决定调用的函数;
  14. 多态性是允许你将父对象设置成为和它的一个或更多的子对象相等的技术;允许将子类型的指针赋值给父类类型的指针。
  15. 虚函数就是允许被其子类重新定义的成员函数;
  16. 覆盖是指子类重新定义父类的虚函数的做法;
  17. 重载是指允许存在多个同名函数,而这些函数的参数表不同。
  18. 重载和多态无关。真正与多态相关的是“覆盖”。当子类重新定义了父类的虚函数后,父类指针根据赋给它的不同的子类指针,动态地调用属于子类的该函数,这样的函数调用在编译期间是无法确定的(调用的子类的虚函数的地址无法给出)。
  19. 封装可以隐藏实现细节,使得代码模块化;继承可以拓展已存在的代码模块(类);它们的目的是为了代码重用。多态则是为了实现另一个目的——接口重用;
  20. 宏、内联函数、模板都可以在编译时解析,唯独虚函数不行,它必须在运行时才能确定;
  21. 友元是一种定义在类外部的普通函数,但它需要在类体内进行说明,为了与该类的成员函数加以区别,在说明时前面加以关键字friend。友元不是成员函数,但它可以访问类中的私有成员。友元的作用在于提高程序的运行效率,但是,它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。
  22. 重载不是一种面向对象的编程,而只是一种语法规则;

继承与接口

  1. 继承特性可以使一个新类获得其父类的操作和数据结构;
  2. 子类获得父类特性的概念就是继承;
  3. 私有继承使父类中所有元素无法与子类联系;
  4. 公有继承方式:基类成员对其对象的可见性与一般类及其对象的可见性相同,公有成员可见,其他成员不可见。这里保护成员与私有成员相同;
  5. 在公有继承时,派生类的对象可以访问基类中的公有成员,派生类不可访问基类中的私有成员;派生类的成员函数可以访问基类中的公有成员和保护成员;
  6. 私有继承方式:基类的公有成员和保护成员都作为派生类的私有成员,并且不能被这个派生类的子类所访问;
  7. 多重继承是一个类从多个基类派生而来的能力;
  8. 在继承中,基类的private对所有的外界都屏蔽(包括自己的派生类),基类的protected控制符对应用程序是屏蔽的,但对其派生类是可访问的;
  9. 类中的每个对象都有一个链表用来存虚方法地址;
  10. 关键字virtual告诉编译器它不应当完成早绑定,相反,它应当自动安装实现晚绑定所必须的机制;
  11. 每个对象里有虚表指针,指向虚表,虚表里存放了虚函数的地址。虚函数表是顺序存放虚函数地址的,不需要用熬链表;
  12. 如果不指定public,C++默认的是私有继承。私有继承是无法继承并使用父类中的公有变量的。
  13. 虚指针或虚函数指针是一个虚函数的实现细节。带有虚函数的类中的每一个对象都有一个虚指针指向该类的虚函数表;
  14. 虚函数的入口地址:
    每个虚函数都在vtable中占了一个表项,保存着一条跳转到它的入口地址的指令(实际上就是保存了它的入口地址)。当一个包含虚函数的对象(注意,不是对象的指针)被创建的时候,它在头部附加一个指针,指向vtable中相应的位置。调用虚函数的时候,不管你是用什么指针调用的,它先根据vtable找到入口地址再执行,从而实现了“动态联编”。而不像普通函数那样简单地跳转到一个固定地址;

位运算与嵌入式编程

  1. RTTI是Runtime Type Information的缩写,从字面上来理解就是执行时期的类型信息,其重要作用就是动态判别执行时期的类型;
  2. 运算符重载就是赋予已有的运算符多重含义。C++中通过重新定义运算符,使它能够用于特定类的对象执行特定的功能;
  3. C++有四个类型转换操作符,这4个操作符是static_cast、const_cast、dynamic_cast和reinterpret_cast;
  4. 不能用static_cast像用C风格的类型转换一样把struct转换成int类型,或者把double类型转换成指针类型;
  5. const_cast最普通的用途就是转换掉对象的const属性;
  6. static_cast在编译时使用类型信息执行转换,在转换执行必要的检测(诸如指针越界计算,类型检查),其操作数相对是安全的;
  7. reinterpret_cast仅仅是重新解释了给出的对象的比特模型,而没有进行二进制转换;
  8. reinterpret_cast是为了映射到一个完全不同类型的意思,这个关键词在我们需要把类型映射会原有类型时用到它;
  9. dynamic_cast是在运行时检查的,dynamic_cast用于在继承体系中进行安全的向下转换downcast,即基类指针\引用到派生类指针\引用的转换;
  10. dynamic_cast是4个转换中唯一的RTTI操作符,提供运行时类型检查;
  11. dynamic_cast不是强制类型转换,而是带有某种“咨询”性质的;
  12. 内存中数据低位字节存入低地址,高位字节存入高地址,而数据的地址采用的低地址来表示;
  13. 当一个对象的值可能会在编译器的控制或监测之外被改变时,例如一个被系统始终更新的变量,那么该对象应该声明为volatile;
  14. volatile修饰符的主要目的是提示编译器该对象的值可能编译器未监测到的情况下被改变,因此编译器不能武断地对引用这些对象的代码做优化处理;
  15. 采用Little-endian模式的CPU对 操作数的存放方式是从低字节到高字节,而Big-endian模式对操作数的存放方式是从高字节到低字节;
  16. c和c++使用的内存拷贝函数,memcpy函数的功能是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。
  17. 在C语言中static的作用是什么:
  • 函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分配一次,因此其值在下次调用时任然维持上次的值;
  • 在模块内的static全局变量可以被模块内所有函数访问,但不能被模块外其他函数访问;
  • 在模块内的static函数只可被这一模块内的其他函数调用,这个函数的使用范围被限制在声明它的模块内;
  • 在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;
  • 在类中的static成员函数属于整个类所拥有,这个函数不接收this指针,因而只能访问类的static成员变量;

数据结构基础

  1. 如果按index访问item并就地插入或删除数据,这种操作比较频繁,那使用数组最节省时间;
  2. 调用函数时首先进行参数压栈,一般情况下压栈顺序为从右到左,最后压函数地址;
  3. 在windows平台上,栈都是从上向下生长的;
  4. 经常操作的内存可分为以下几个类别:
  • 栈区(stack):由编译器自动分配和释放,存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈
  • 堆区(heap):一般由程序员分配和释放,若程序员不释放,程序结束时可能由操作系统回收分配方式类似于链表;
  • 全局区(静态区)(static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后有系统释放;
  • 文字常量区:常量字符就是放在这里的。程序结束后有系统释放;
  • 程序代码区:存放函数体的二进制代码;
  1. 堆:首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆节点,然后将该节点从空闲节点链表中删除,并将该节点的空间分配给程序;
  2. 栈:在windows下,栈是向低地址扩展的数据结构,是一块连续的内
  3. heap与stack的区别:
    heap是堆,stack是栈;
    stack的空间由系统自动分配和释放,heap上的空间手动分配和释放;
    stack空间有限,heap是很大的自由存储区;
    C中的malloc函数分配的内存空间即在堆上,C++中对应的是new操作符;
    程序在编译期对变量和函数分配内存都在栈上进行,且程序运行过程中函数调用时参数的传递也在栈上进行;
  4. 存区域;能从栈获得的空间较小;
  5. 堆:堆是向高地址扩展的数据结构,是不连续的内存空间;堆获得的空间比较灵活,也比较大;
  6. 对于一个进程的内存空间而言,可以在逻辑上分成3个部分:代码区、静态数据区和动态数据区;
  7. 动态数据区一般就是“堆栈”。栈是一种线性结构,堆是一种链式结构。
  8. 二叉树遍历原则:前序遍历是根左右,中序遍历是左根右,后序遍历是左右根;
  9. 二叉搜索树:对于树中的每个节点X,它的左子树中所有关键字的值都小于X的关键字值,而它的右子树中的所有关键字值都大于X的关键字值;
  10. 搜索、插入、删除的复杂度等于树高,即O(log(n));
  11. 平衡二叉树具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右子树都是一棵平衡二叉树;
  12. A、B两棵树相等当且仅当RootA->c==RootB->c,而且A和B的左右子树对应相等或者左右互换后相等;
  13. 深度优先遍历:
    1>首先访问出发点v,并将其标记为已访问过;然后依次从v出发搜索v的每个邻接点w;
    2>若w未曾访问过,则以w为新的出发点继续进行深度优先遍历,直至图中所有和源点v有路径相通的顶点(亦称为从源点可达的顶点)均已被访问为止;
    3>若此时图中仍有未访问的顶点,则另选一个尚未访问的顶点作为新的源点重复上述过程,直至图中所有顶点均已被访问为止;
  14. 广度优先遍历:
    1>从图中某个顶点V0出发,并访问此顶点;
    2>从V0出发,访问V0的各个未曾访问邻接点W1,W2,...,Wk;然后,依次从W1,W2,...,Wk出发访问各自未被访问的邻接点;
    3>重复步骤2,直到全部顶点都被访问为止;
  15. 评价算法好坏的两条标准:执行时间和所需的辅助空间、算法本身的复杂程度
  16. 分治法的基本思想是将原问题分解为若干个规模更小但结构与原问题相似的子问题。递归地解决这些子问题,然后将这些子问题得解组合为原问题的解;
  17. 快速排序算法是一种不稳定的排序算法,平均时间复杂度O(nlogn),最差情况时间复杂度为O(n2);
  18. 冒泡排序最好的时间复杂度为O(n),最坏的时间复杂度为O(n的平方);平均时间复杂度为O(n的平方);冒泡排序是就地排序,且它是稳定的;
  19. 希尔排序的时间性能优于直接插入排序,希尔排序是不稳定的;
  20. 若n较小,可采用直接插入排序或直接选择排序;
  21. 若文件初始状态基本有序(指正序),则应该选择直接插入排序、冒泡排序或随机的快速排序;
  22. 若n较大,则采用时间复杂度为O(nlogn)的排序算法(快速排序、堆排序、归并排序)
  23. 时间复杂度:O(1)<O(log(2)n)<O(n)<O(nlog(2)n)<O(n^2)<O(n^3)<O(2^n)
  24. 时间复杂度都不带常数项或者常熟系数的;
  25. 当遇到键-值对存储,采用Hashtable比ArrayList查找的性能高;

字符串

1、字符串拷贝
char *strcpy(char *strDest,char *strSrc){
    // 使用断言(assert)可以创建更稳定,品质更好且不易于出错的代码。当需要在一个值为FALSE时中断当前操作的话,可以使用断言。
    assert((strDest!=NULL)&&(strSrc!=NULL));
    char *address=strDest;
    while((*strDest++=*strSrc++)!='\0')
    NULL;
    return address;
}

2、动态内存分配
特点:不需要预先分配存储空间;
           分配的空间可以根据程序的需要扩大或缩小;

malloc函数:void *malloc(unsigned int size)
    其作用是在内存的动态存储区域中分配一个长度为size的连续空间。其参数是一个无符号整型数,返回值是一个指向所分配的连续存储区域的起始地址的指针;

例如:if(array(int *)malloc(10*sizeof(int)))语句可分为以下几步
  • 分配10个整型的连续空间,并返回一个指向起始地址的整型指针
  • 把此整型指针地址赋给array
  • 检测返回值是否为NULL


  1. 字符数组和字符串这明显的区别就是字符串会被默认地加上结束符’\0‘;
  2. 头文件iostream中含有cin、cout、cerr几个对象,对应于标准输入流、标准输出流和标准错误流;
  3. 1) malloc 函数: void *malloc(unsigned int size) 在内存的动态分配区域中分配一个长度为size的连续空间,如果分配成功,则返回所分配内存空间的首地址,否则返回NULL,申请的内存不会进行初始化。 
    2)calloc 函数: void *calloc(unsigned int num, unsigned int size)
    按照所给的数据个数和数据类型所占字节数,分配一个 num * size 连续的空间。calloc申请内存空间后,会自动初始化内存空间为 0,但是malloc不会进行初始化,其内存空间存储的是一些随机数据。  
    3)realloc 函数: void *realloc(void *ptr, unsigned int size) 动态分配一个长度为size的内存空间,并把内存空间的首地址赋值给ptr,把ptr内存空间调整为size。申请的内存空间不会进行初始化。 
    4)new是动态分配内存的运算符,自动计算需要分配的空间,在分配类类型的内存空间时,同时调用类的构造函数,对内存空间进行初始化,即完成类的初始化工作。动态分配内置类型是否自动初始化取决于变量定义的位置,在函数体外定义的变量都初始化为0,在函数体内定义的内置类型变量都不进行初始化。


设计模式与软件测试

  1. 设计模式是经过总结形成的一套某一类问题的一般性解决方案,而不是设计出来的定性规则;
  2. 设计模式关注的重点在于通过经验提取的”准则或指导方案“在设计中的应用;
  3. 模式的目标是把共通的问题中的不变部分和变化部分分离出来。不变的部分,就构成了模式;
  4. 软件测试是使用人工或者自动手段来运行或测试某个系统的过程,其目的在于检验软件是否满足规定的需求或弄清预期结果与实际结果之间的差别;
  5. 桥梁模式(Bridge):将抽象化(Abstraction)与实现化(Implementation)脱耦,使得二者可以独立地变化;
  6. Bridge模式将继承关系转换为组合关系,从而降低了系统间的耦合;
  7. 当对一个类应用 sealed 修饰符时,此修饰符会阻止其他类从该类继承。
  8. 单例模式:Singleton就是确保一个类只有唯一的一个实例。Singleton主要用于对象的创建,这意味着,如果某个类采用了Singleton模式,则在这个类被创建后,它将有且仅有一个实例可供访问。
  9. 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题帮助。这个帮助对象在状态上发生变化时,会通知所有对象,使它们能够自动更新自己;
  10. 自动化测试为何重要?
    自动化测试可以让测试人员从枯燥无味的手工重复性测试中解放出来,并且提高工作效率,通过自动化测试结果来分析功能和性能上的缺陷;
  11. 描述一个测试结束的准则:
    一个测试结束的标准可以查看已提交bug是否已经全部解决并已验证关闭,一般来说,bug验证率在95%以上,并且没有大的影响功能的bug处于未解决状态,就可以测试通过;
  12. 一个测试计划中能包含的内容:
    在一个测试计划中可以包含需要测试的产品的特点和主要功能模块,列出需要测试的功能点,并标明侧重点;测试的策略和记录(测试工具的确认,测试用例等文档,测试方法的确定);测试资源配置(确定测试每一阶段的任务和所需的资源);
  13. 功能测试主要是黑盒测试,由测试人员进行,主要验证产品是否符合需求设计的要求;
  14. 可用性测试主要是由用户来进行,主要对产品的易用性进行测试,包括有效性、效率和用户主观满意度。其中有效性指用户完成特定任务和达到特定目标时所具有的正确和完整程度;效率指用户完成任务的正确和完整程度与所使用资源之间的比率;满意度指用户在使用过程中所感受到的主观满意和接受程度;
  15. 黑盒测试包括边界值测试、健壮性测试、最坏情况测试、特殊值测试、随机测试;
  16. 白盒测试有几种测试方法:条件覆盖、路径覆盖、语句覆盖、分支覆盖。其中分支覆盖又称判定覆盖,使得程序中每个判断的取真分支和取假分支至少经历一次,即判断的真假均曾被满足;
  17. 白盒测试的测试方法有代码检查法、静态结构分析法、静态质量度量法、逻辑覆盖法、基本路径测试法、域测试、符号测试、Z路径覆盖等方法;
  18. 基本路径测试法是在程序控制流图的基础上,通过分析控制结构的环路复杂性,导出基本可执行路径集合,从而设计测试用例的方法。设计出的测试用例要保证在测试中程序的每个可执行语句至少执行一次;

操作系统

  1. 作业:用户在一次解题或一个事务处理过程中要求计算机系统所做工作的集合。它包括用户程序、所需要的数据及控制命令。作业是由一系列有序的步骤组成的;
  2. 进程:一个程序在一个数据集合上的一次运行过程。所以一个程序在不同集合上运行,乃至一个程序在同样数据集合上的多次运行都是不同的进程;
  3. 线程:线程是进程中的一个实体,是被系统独立调度和执行的基本单位;
  4. 管程:管程实际上是定义了一个数据结构和在该数据结构上的能为并发进程所执行的一组操作,这组操作能同步进程和改变管程中的数据;
  5. 进程间的通信:现在最常用的进程间的通信的方式有信号、信号量、消息队列、共享内存;
  6. 所谓进程通信,就是不同进程之间进行一些”接触“。
  7. 信号和信号量是不同的,它们虽然都可用来实现同步和互斥,但信号是使用信号处理器来进行的,信号量是使用P、V操作来实现的;
  8. 消息队列是比较高级的一种进程间通信方法,因为它真的可以在进程间传送message;
  9. 一个消息队列可以被多个进程所共享;如果一个进程的消息太多,一个消息队列放不下,也可以用多于一个的消息队列;
  10. 共享消息队列的进程所发出送的消息除了message本身外还有一个标志,这个标志可以指明该消息将由哪个进程或者是哪类进程接受。每一个共享消息队列的进程针对这个队列也有自己的标志,可以用来声明自己的身份;
  11. 互斥器(mutex)与临界区(critical section)的区别:mutex可以用于进程之间互斥,critical section是线程之间的互斥;
  12. 短作业优先=最短剩余时间作业优先;
  13. 在多重处理系统中,处理死锁的办法有两种:一是防止其发生;二是发生后处理;
  14. 死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时系统处于死锁状态或系统产生了死锁;
  15. 产生死锁的4个必要条件:
    互斥条件:一个资源每次只能被一个进程使用;
    请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放;
    不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺;
    循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系;
  16. 预防死锁产生的3个措施:
    采用资源静态分配策略,破坏”部分分配“条件;
    允许进程剥夺使用其他进程占有的资源,从而破坏”不可剥夺“条件;
    采用资源有序分配法,破坏”环路“条件;
  17. fork()进程从这里分叉,分成了两个进程:一个是父进程,一个子进程;
  18. 进程的三个基本状态:
    就绪状态:当进程已分配到除CPU以外的所有必要的资源,只要获得处理机便可立即执行,这时的进程状态称为就绪状态;
    执行状态:当进程已获得处理机,其程序正在处理机上执行,此时的进程状态称为执行状态;
    阻塞状态:正在执行的进程,由于等待某个事件发生而无法执行时,便放弃处理机而处于阻塞状态。引起进程阻塞的事件可以有多种,例如,等待I /O完成、申请缓冲区不能满足、等待信号等。
  19. 进程和线程的差别:
    进程是程序的一次执行。线程可以理解为进程中执行的一段程序片段。
    进程间是独立的,这表现在内存空间、上下文环境上;线程运行在进程空间内。一般来讲,进程无法突破进程边界存取其他进程内的存储空间;而线程由于处于进程空间内,所以同一进程所产生的线程共享同一内存空间;
    线程是属于进程的,当进程退出时该线程所产生的线程都会被强制退出并清除。线程占用的资源少于进程所占用的资源。进程和线程都可以有优先级;
  20. PE文件被称为可移植的执行体是Portable Execute的全称,常见的EXE、DLL、OCX、SYS、COM都是PE文件;
  21. 静态库本身就包含了实际执行代码、地址符号表等等,而对于导入库而言,其实际执行代码位于动态库中,导入库只包含了地址符号表等,确保程序找到对应函数的一些基本地址信息;
  22. 静态链接库中不能再包含其他的动态链接库或者静态库,而动态链接库中还可以再包含其他的动态或静态链接库;
  23. 进程有两个部分构成:一个是进程内核对象,另一个是地址空间;
  24. 线程由两个部分组成:一个是线程内核对象,另一个是线程堆栈,它用于维护线程在执行代码时需要的所有函数参数和局部变量;
  25. windows内存管理方式主要分为:页式管理、段式管理、段页式管理。
  26. 页式管理的基本原理是将各进程的虚拟空间划分成若干个长度相等的页;页式管理把内存空间按页的大小划分成片或页面,然后把页式虚拟地址与内存地址建立一一对应的页表;并用相应的硬件地址变换机构来解决离散地址变换问题;
    优点:没有外碎片,每个内碎片不超过页的大小;
    缺点:程序全部装入内存,要求有相应的硬件支持;
  27. 段式管理的基本思想就是把程序按内容或过程函数关系分成段;段式管理程序以段为单位分配内存,然后通过地址影射机构把段式虚拟地址转换为实际内存物理地址;
    优点:可以分别编写和编译,可以针对不同类型的段采取不同的保护,可以按段为单位来进行共享,包括通过动态链接进行代码共享。
    缺点:会产生碎片
  28. 段页式管理:为了实现段页式管理,系统必须为每个作业或进程建立一张段表以管理内存分配与释放、缺段处理等;另外每一个段又被划分成了若干页。每个段又必须建立一张页表以把段中的虚页变换成内存中的实际页面;
  29. Belady现象:采用FIFO算法时,如果对一个进程未分配它所要求的全部页面,有时就会出现分配的页面数增多但缺页率反而提高的现象;
  30. 内存抖动(Thrashing)一般是内存分配算法不好,内存太小或者程序的算法不佳引起页面频繁地从内存调入调出的行为;
  31. 虚拟存储器的基本思想是程序、数据、堆栈的总的大小可以超过物理存储器的大小,操作系统把当前使用的部分保留在内存中,而把其他未被使用的部分保存在磁盘上;
  32. LRU算法的提出,基于这样一个事实:在前面几条指令中使用频繁的页面,很可能在后面的几条指令中频繁使用。反过来说,已经很久没有使用的页面,很可能在未来较长的一段时间内不会被用到。
  33. 1、什么是临界区? 
    答:每个进程中访问临界资源的那段程序称为临界区(临界资源是一次仅允许一个进程使用的共享资源)。每次只准许一个进程进入临界区,进入后不允许其他进程进入。  
  34. 2、进程进入临界区的调度原则是:  
    ①如果有若干进程要求进入空闲的临界区,一次仅允许一个进程进入。②任何时候,处于临界区内的进程不可多于一个。如已有进程进入自己的临界区,则其它所有试图进入临界区的进程必须等待。③进入临界区的进程要在有限时间内退出,以便其它进程能及时进入自己的临界区。④如果进程不能进入自己的临界区,则应让出CPU,避免进程出现“忙等”现象。
  35. 线程共享的环境包括:进程代码段、进程的公有数据(利用这些共享的数据,线程很容易的实现相互之间的通讯)、进程打开的文件描述符、信号的处理器、进程的当前目录和进程用户ID与进程组ID。

数据库与SQL语言

  1. 数据库模式的4个范式问题:
    (1)如果关系模式R的所有属性的值域中每一个值都是不可再分解的值,则称R属于第一范式模式;第一范式的模式要求属性值不可再分裂成更小的部分,即属性项不能是属性组合或由组属性组成;
    (2)如果关系模式R为第一范式,并且每一个非主属性完全函数依赖于R的某个候选键,则R为第二范式模式。
    (3)如果关系模式R是第二范式,且非主属性都不传递依赖于R的候选键,则称R是第三范式的模式。
    (4)BC范式。如果关系模式R是第一范式,且每个属性都不传递依赖于R的候选键,那么称R为BCNF的模式;
    (5)设R是一个关系模式,D是R上的多值依赖集合。如果D中成立非平凡多值依赖X——Y,X必是R的超键,那么称R是第四范式模式;
  2. 存储过程和函数的区别:
    存储过程是用户定义的一系列SQL语句的集合,涉及特定表或其他对象的任务,用户可以调用存储过程。而函数通常是数据库已定义的方法,它接收参数并返回某种类型的值,并且不涉及特定用户表;
  3. 数据库事务是指作为单个逻辑工作单元执行的一系列的操作,这些操作要么全做要么全不做,是一个不可分割的工作单位;
  4. 事物的开始与结束可以由用户显式控制。如果用户没有显式地定义事务,则由DBMS按默认规定自动划分事务。事务具有原子性、一致性、独立性及持久性等特点;
  5. 事务的原子性是指一个事务要么全部执行,要么不执行;
  6. 事务的一致性是指事务的运行不改变数据库中数据的一致性;
  7. 事务的独立性是指两个以上的事务不会出现交错执行的状态;
  8. 事务的持久性是指事务运行成功以后,就系统的更新是永久的。不会无缘无故的回滚;
  9. 游标的作用:游标用于定位结果集的行。通过全局变量@@FETCH_STATUS可以判断是否到了最后。通常此变量不等于0表示出错或到了最后;
  10. 事前触发和事后触发的区别:事前触发器运行于触发事件发生之前,而事后触发器运行于触发事件发生之后。
  11. 语句级触发和行级触发的区别:语句级触发器可以在语句执行前或后执行,而行级触发在触发器所影响的每一行触发一次;
  12. SQL注入式攻击:就是攻击者把SQL命令插入到Web表单的输入域或页面请求的查询字符串中,欺骗服务器执行恶意的SQL命令;
  13. 防范SQL注入式攻击:在利用表单输入的内容构造SQL命令之前,把所有输入内容过滤一番;主要有:
    替换单引号,即把所有单独出现的单引号改成两个单引号,防止攻击者修改SQL命令的含义
    删除用户输入内容中的所有连字符,防止攻击者顺利获得访问权限;
    对于用来执行查询的数据库账户,限制其权限;
    用存储过程来执行所有的查询;
    检查用户输入的合法性,确信输入内容只包含合法的数据;
    将用户登录名称、密码等数据加密保存;
    检查提取数据的查询所返回的记录数量;
  14. 聚集索引和非聚集索引的区别:聚集索引的顺序就是数据的物理存储顺序,而对非聚集索引的解释是索引顺序与数据物理排列顺序无关正是因为如此,所以一个表最多只能有一个聚集索引;
  15. 在SQL Server中,索引是通过二叉树的数据结构来描述的,我们可以这么理解聚集索引:索引的叶节点就是数据节点。而非聚集索引的叶节点仍然是索引节点,只不过有一个指针指向对应的数据块;
  16. 创建一张临时表:
    create table #Temp(字段1类型,字段2类型......)
  17. 复制表:只复制结构,源表名:A,新表名:B
    select * into B from A where A=1
  18. 拷贝表:拷贝数据,源表名:A,新表名:B
  19. 找出表ppp里面num最小的数,不能使用min函数:
    select * from ppp where num<=all(select num from ppp)
  20. 找出表ppp里面num最小的数,可以使用min函数:
    select * from ppp where num=(select Min(num) from ppp)
  21. 选择表ppp2中num重复的记录:
    select * from ppp2 where num in(select num from ppp2 group by num having(count(num)>1))
  22. sp_renamedb可以更改数据库的名称;
  23. 只有sysadmin和dbcreator固定服务器角色的成员才能执行sp_renamedb;

计算机网络及分布式系统

  1. 在OSI参考模型中,物理层的作用是透明的传输比特流。对等实体在一次交互作用中传达的信息单位称为协议数据单元,它包括控制信息和用户数据。上下层实体之间的接口称为服务访问点(SAP),网络层的访问服务点也称为网络地址,通常分为网络号和主机地址两部分;
  2. 物理层涉及在信道上传输的原始比特流;
  3. 数据链路层的主要任务是加强物理层传输原始比特流的功能,使之对应的网络层显现为一条无错线路。发送包把输入数据封装在数据帧,按顺序传送出去并处理接收方回送的确认帧;
  4. 网络层关系到子网的运行控制,其中一个关键问题是确认从源端到目的端如何选择路由;
  5. 传输层的基本功能是从会话层接收数据而且把其分成较小的单元传递给网络层;
  6. TCP和UDP有什么区别:
    TCP:TCP是传输控制协议,提供的是面向连接、可靠的字节流服务。当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能传输数据。TCP提供超时重发、丢弃重复数据、检验数据、流量控制等功能,保证数据能从一端到另一端。
    UDP:UDP是用户数据包协议,是一个简单的面向数据报的运输层协议。UDP不提供可靠性,它只是把应用程序传送给IP层的数据报发送出去,但是并不保证它们能到达目的地。由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快;
  7. ICMP是Internet控制报文协议,用于传输出错报告控制信息;
  8. Ping程序一般用来测试一台主机是否可达,该程序发送一份ICMP回显请求报文给主机,并等待返回ICMP回显 应答。
  9. 包未到达终点不可能重组,但可以分散成碎片;
  10. 防火墙的优点:它能增强机构内部网络的安全性,用于加强网络间的访问控制,防止外部用户非法使用内部网的资源,保护内部网络的设备不被破坏,防止内部网络的敏感数据被窃取。防火墙系统决定了哪些内部服务可以被外界访问;外界的哪些人可以访问内部的哪些服务,以及哪些外部服务可以被内部人员访问;
  11. 防火墙的缺点:对于发生在内网的攻击无能为力;对于部分攻击,可以绕过防火墙,防火墙发现不了;防火墙的策略是静态的,不能试试动态防御;
  12. 入侵检测的优势:入侵检测系统扫描当前网络的活动,监视和记录网络的流量,根据定义好的规则来过滤从主机网卡到网线上的流量;
  13. 入侵检测的缺点:目前入侵检测技术的方法主要停留在异常检测统计方法和误用检测方法上,这两种方法都还存在这样或那样的问题;
  14. 25端口为SMTP(简单邮件传输协议)服务器所开放,主要用于发送邮件;
  15. 利用25端口,黑客可以寻找SMTP服务器,用来转发垃圾邮件。
  16. CSMA/CD并不能完全避免冲突,只是发生冲突之后,会检测到冲突的存在,于是在一定时间之后再继续冲突检测,再次发送!

多看几遍!多看几遍!多看几遍!


你可能感兴趣的:(程序员面试宝典)