2012年面试题集

2012年5月份百度实习生招聘笔试题

1、C和C++动态内存分配与释放的区别?


 

5月6号去百度暑期实习招聘现场打了满满一瓶酱油,尽管进行了网申,但是没有收到百度的笔试通知,只好和几名同时没有收到通知的好友一同去复旦霸笔 了,复旦五角场校区算是一个故地,因为之前腾讯实习招聘笔试也是在这里进行的,幸运的是腾讯出的考题都比较基础,有幸通过了笔试筛选进入了一轮面试,本人 水平有限也就这能止步一轮面了,已经很高兴了,并不奢望收到腾讯或百度的橄榄枝,只是希望在参加这样的笔试面试的过程中不断查漏补缺,增加经验,不断提高 自己,希望正式找工作的时候能够满足名企的要求。

言归正传,回到百度笔试题目上面,百度笔试题目明显和腾讯有着截然不同的风格,腾讯比较注重基础能力,而百度更注重解决实际问题的能力,只给出六道 大题,基本上是与实际问题相结合的,很重视应试人对程序算法、数据结构的理解,这里不谈那些发散性的问题,这里只谈论基础问题,因为我觉得一切伟大的建筑 都是基于牢固基石的,掌握好基础才能掌握更高深的技术。

其中一道很基础的问题是问C和C++在动态内存分配,释放方面的区别。作为一个励志成为C和C++软件开发人员,居然连这个问题都解答的含糊不清,深感惭愧,这才认真总结一番。

一、先来谈谈在C语言下,动态内存分配和释放的特点。

动态分配内存的定义是这样的,指在程序运行过程中,要申请内存,系统会根据程序的实际情况来分配,分配空间的大小是由程序的需求来决定的。在C语言 下面,举个例子,定义一个指针,int *p;此时指针i是一个野指针,是一个指向不确定位置的指针,对它进行操作是很危险的,此时我们需要动态分配内存空间,让i指向它。而有一种形式是这样 的,int *p=&b;这并非是一种动态内存分配方式,而是一种指针的初始化,把变量b的首地址给了指针p。在C语言下究竟如何实现动态内存分配的呢?这里 提供了几个函数来实现,分别是malloc(),calloc(),realloc(),而释放内存的函数为free(),分别探讨他们的异同。

1.malloc函数

  函数原型为void *malloc(unsigned int size);在内存的动态存储区中分配一块长度为"size" 字节的连续区域。函数的返回值为该区域的首地址。 “类型说明符”表示把该区域用于何种数据类型。(类型说明符*)表示把返回值强制转换为该类型指针。“size”是一个无符号数。例如: pc=(char *) malloc (100); 表示分配100个字节的内存空间,并强制转换为字符数组类型,函数的返回值为指向该字符数组的指针,把该指针赋予指针变量pc。若size超出可用空间, 则返回空指针值NULL。

2.calloc 函数

函数原型为void *calloc(unsigned int num, unsigned int size)

  按所给数据个数和每个数据所占字节数开辟存储空间。其中num为数据个数,size为每个数据所占字节数,故开辟的总字节数为 num*size。函数返回该存储区的起始地址。calloc函数与malloc 函数的区别仅在于一次可以分配n块区域。例如: ps=(struct stu*) calloc(2,sizeof (struct stu)); 其中的sizeof(struct stu)是求stu的结构长度。因此该语句的意思是:按stu的长度分配2块连续区域,强制转换为stu类型,并把其首地址赋予指针变量ps。

3. realloc函数:

  函数原型为void *realloc(void *ptr, unsigned int size)

重新定义所开辟内存空间的大小。其中ptr所指的内存空间是用前述函数已开辟的,size为新的空间大小,其值可比原来大或小。函数返回新存储区的 起始地址(该地址可能与以前的地址不同)。例如p1=(float *)realloc(p1,16);将原先开辟的8个字节调整为16个字节。

**动态申请的内存空间要进行手动用free()函数释放

4. free函数:

  函数原型为void free(void *ptr)

  将以前开辟的某内存空间释放。函数原型为 void free(void *ptr)其中ptr为存放待释放空间起始地址的指针变量,函数无返回值。应注意:ptr所指向的空间必须是前述函数所开辟的。例如free((void *)p1);将上例开辟的16个字节释放。可简写为free(p1);由系统自动进行类型转换。

二、C++语言动态内存分配

C++语言中用new和delete来动态申请和释放内存。

1. 申请单个对象

  int *p;

  p=new int;或者 p=new int(value);

  2. 动态申请数组

  int *p;

  p=new int [100];

  这样可以申请长度为100的数组,但是不能进行初始化。

 3. delete

  int *p, *q;

  p=new int;

  q=new int[10];

  delete p;

  delete [ ]q;

分享来源:http://www.cnblogs.com/zhj202190/archive/2011/05/11/2043620.html

http://apps.hi.baidu.com/share/detail/57234849


2012年10月18号百度PC客户端岗位一面电话面试面试题:

前奏:因为阿里巴巴的面 试不能由大连调北京,我就风尘扑扑的从北京回到大连去面阿里巴巴,尽管知道在就业形势很不好的今年进阿里巴巴的机会很渺茫,但是还是想试一把,所以就回去 了,正好在回去的时候收到的百度的面试,由于不在北京,就电话面了,其实在会大连之前笔试百度过之后,就知道肯定会有面试

2012年10月22号百度客户端二面面试题:

1、select函数的介绍

(1)一些小的知识点比如 select() 函数中第一个参数 int maxfdp 为什么要是最大的文件描述符的值 +1 ,当时临阵磨枪的看了下select函数,细致的知识点答不上来,参考http://blog.csdn.net/leo115/article/details/8097143

2、C++中一个类的大小如何确定?

这个以前没看过,就是分析了一下,结果露出了自己对虚函数理解的严重错误的马脚,接下来分析一下C++中类的大小:

(1)在一个C++类中,如果什么都没有,则这个类只占有1个字节;说明:如果一个类中没有任何数据成员,则这个类实际上是不占用存储空间的,size = 0;但是0不好在内存中定义一个地址,所以我们就人为的规定了大小为0的一个对象所占的存储空间的大小为1。

(2)一旦这个类中有其他的一些数据成员,比如说一个 int data ;那么这个类的大小就为 4 个字节,而不是5个字节,上述的一个字节不计算在内;

(3)普通的成员函数是不占用空间的,所以一个只用普通函数的类的大小只占有 1 个字节。说明:普通成员函数是类的所有对象所通用的方法,不算做对象的成员,所以不能算在对象的存储空间内。

(4)对于有虚函数的类,因为要存在一个虚函数表,需要4个字节,(是一个数组指针vptr,数组中存储的是虚函数的函数指针的地址),这个指向虚函数表的指针占用4个字节的存储空间。

(5)注意将数据对齐考虑进去,如一个类中含有 虚函数 和  一个char型数据,sizeof(class) = 8 ;默认对齐是 4字节对齐。

理解参考这个:http://blog.163.com/xping_lsr/blog/static/19654034520119804131721/

3、聊了一下虚函数机制,虚函数表这一块理解的粗枝大叶,答得很狼狈:

(1)竟然理解成了 虚函数表中可以存储普通函数的函数指针地址,参考http://blog.csdn.net/leo115/article/details/8035078

(2)这个虚函数表是所有的类的实例都共用这个虚函数表呢?还是每个实例都会有一个虚函数表的copy版本?

4、Linux下的一个文件 /proc 这个目录是存放什么的?如何查看当前跑的进程的最大数量?如果查看当前所打开的文件的数量?如何查看当前所建立的连接?统计当前建立的连接的数量?

我在Linux环境下周游了一年多的时间,感觉对这个平台还算很熟悉吧,但是对于面试 官提出的几个命令,表示都没有接触过,再者就是忘了, 再者就是完全没用到,对于第一个命令,这个目录是是linux下的一个伪文件系统,里边存储一些与 进程相关的,系统相关的,以及系统子系统部分,可以直接通过cat / echo 直接输出一些用户需要的内核信息。平时在做多线程编程的时候更多的调用继承开发环境自带的库函数,可能是自己所操作的线程比较少 或者是 平时做的项目的深度确实没达到,都是一些浅层面的操作,导致自己根本没有掌握这么多知识,只的表示不会。

5、进程和线程之间的区别?什么是“线程安全”?

简单的介绍:进程是动态运行的程序的实例,是操作系统分配资源的基本单位,每一个进程都是一个实体,都有自己的地址空间,(包括:文本区域,数据区域,堆栈),进程是运行中的程序。线程是 进程中某单一顺序的控制流,也被称为轻量级进程,是运行中的程序的调度的基本单位,说明:单一顺序的控制流,每个独立的线程都有一个程序的入口、运行队列和程序的出口。但是线程不能独立的执行,必须存在应用程序中,由应用程序提供多个线程执行控制。

(0)一个程序至少拥有一个进程(通过fork创建进程),一个进程至少拥有一个线程(必有一个主线程)。

(1) 从调度方面考虑,线程是作为调度和分配的基本单位,进程是作为拥有资源的基本单位,线程是CPU和内存的真正的使用者

(2)并发性方面考虑:不仅相同进程中的线程可以并发,不同进程中线程之间也是可以并发的;同时进程与进程之间也是可以并发的

(3)拥有资源:进程拥有自己独立的地址空间,而线程不拥有系统资源,但是可以访问所在的进程的资源。

(4)系统开销方面:在创建和撤销进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建和撤销线程时的开销。

接着解释第二个问题 什么是“线程安全”?

(1)如果程序代码所在的进程中有多个线程在同时运行,这些线程可能会同时运行这段代码,如果每次运行的结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的一样,就是线程安全的。

(2)或者说:一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口执行的结果产生二义性,也就是说我们不用考虑同步问题,这个时候线程是安全的。

(3)线程安全问题往往是由全局变量及静态变量引起的。

(4)一般来说若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量的线程是安全的;若有多个线程同时执行写操作,一般要考虑线程同步问题,线程同步的解决办法一般是:临界区、信号量、互斥锁等


6、最后问了一道算法题:

有两个字符串数组: string src[]  和 string des[] ,每个字符串数组的长度都是10W跳左右,每个字符的 size<1KB ,设计一个算法 查找 两个字符串数组中想交的字符串。

解析方法:

分析 10W = 2^20  1KB*10W*2 = 2GB ,当今的内存中正好可以容下这么多数据,算法设计

(1)遍历字符串数组src,构造一个 tire tree(字典数),然后遍历字符串数组des遇到已经存储过的相同的结构则输出。

(2)设计一个hash,关键是哈希算法的设计,因为这是一个字符串数组,每个字符都 是有范围的(0~25),我们可以字符串数组中的每个字符串看成一个26进制的数,将其转化为10进制,这样就可以得到一个唯一的key值,对于字符串太 长的情况下,我们可以将这个字符串对10万取模,对10万取模后,我们并不能保证这个key唯一,这样我们就需要key值冲突处理,参考以下四种处理方 式:http://blog.csdn.net/leo115/article/details/8052353


11月3号青牛软件面试

青牛软件的一面就是聊项目,没有做题,然后遇到下面的一个问题:

1、操作系统中 什么是临界区?什么是临界资源? 举例说明!

答:操作系统中对临界区的定义是这样的:每个进程中访问临界资源的那段程序称为临界区。临界资源的定义是:临界资源可以由多个进程所共享,但是一次仅能由一个进程访问的共享资源。  临界区要求每次只准许一个进程进入临界区,占时拥有临界资源;

临界资源的举例:打印机,磁盘等, 一个全局变量可以允许多个进程访问,所以全局变量不是临界资源。

 

转自:http://blog.csdn.net/leo115/article/details/8111926

posted on 2012-12-13 21:32  猿人谷  阅读(271)  评论(0编辑  收藏  举报