#include <stdlib.h>
typedef struct foo
{
int x;
int y;
unsigned long ptr;
char* buffer;
}foo_t;
代码一:
考察考生对可执行文件空间结构的认识.堆,栈,初始化空间及未初始化空间的作用.
foo_t* factory(int x,int y)
{
foo_t fp;
// foo_t* fp = (foo_t*)malloc(sizeof(foo_t));
if(x>0 && x < 1024)
fp.x = x;
//fp->x = x;
if(y>0 && y < 768)
fp.y = y;
//fp->y = y;
return &fp;
//return fp;
}
代码二:
考察考生对变量及变量指针声明时是否分配可用空间的理解.
int add_buffer()
{
foo_t* fp;
/*
need malloc before use a pointer.
*/
//fp = (foo_t*)malloc(sizeof(foo_t));
fp->buffer = "hello alibaba";
printf("BUFFER => %s\n",fp->buffer);
/*
need free the malloced pointer.
*/
//free(fp);
return 0;
}
代码三:
考察考生是否对细节足够仔细.
该段代码是RSHASH算法的变形,要对输入的字符串逐个作HASH运算,但while循环中条件写错,导致死循环.
unsigned int Hash(char *str)
{
unsigned int b = 378551;
unsigned int a = 63689;
unsigned int hash = 0;
/*
str need ++
*/
while (*str)
{
hash = hash * a + (*str);
a *= b;
}
return hash;
}
代码四:
考察考生对多线程操作的理解,本题目的陷阱在于对一个多线程共享的全局变量做自加操作时,是否需要加锁.
这个题目代码较多,但结构很清晰,如果考生不能正确阅读多线程调度的代码,则不能准确定位到问题.
一个函数dobench用作并发调度,其中关键结构体如下:
typedef struct bench
{
void* func;//业务函数
void* param;//业务参数
long n;//每个线程要执行的次数
long count;//并发计数器
long num;//并发的线程总数
pthread_cond_t cond;
pthread_mutex_t mutex;
}bench_t;
该函数的调用方式如下:
pthread_t tid;
for(i = 0; i < p->num; ++i)
{
/* 通过多线程并发执行 */
if (pthread_create(&tid,NULL,dobench,p) < 0) {
syslog(LOG_ERR, "Create thread failed. - %m\n");
}
syslog(LOG_NOTICE, "Created a thread.\n");
}
b的类型为bench_t.
dobench的原型如下:
void dobench(void* param)
{
int i;
void(* func)(void* param);
struct bench * p = (struct bench *) param;
struct timeval tvStart,tvEnd;
func = p->func;
syslog(LOG_NOTICE, "Thread[%lld] dobench variables inited.\n",pthread_self());
//起始时间
gettimeofday(&tvStart,NULL);
if (p->n > 0) {
for (i=0; i < p->n; i++) {
func((void*)p->param);
}
}
else {
syslog(LOG_NOTICE, "struct bench * p->n should graet than 0\n");
}
//终止时间
gettimeofday(&tvEnd,NULL);
double dif;
dif = 1000000*(tvEnd.tv_sec-tvStart.tv_sec) + (tvEnd.tv_usec-tvStart.tv_usec);
syslog(LOG_NOTICE,"Thread[%lld] Cost => %f\n",pthread_self(),dif);
/*
加锁->计数器加一->条件变量触发->解锁
每当一个线程迭代完成指定的任务时,都要通过条件变量通知主线程.
*/
//pthread_mutex_lock(&p->mutex);
p->count++;
pthread_cond_signal(&p->cond);
//pthread_mutex_unlock(&p->mutex);
return;
}
传递给dobench的参数param是个全局变量, param->num是要启动工作的线程总数.
主线程通过param->count这个计数器来判断当前已执行完的线程数,是否等于param->num,如果等于,则表示所有的线程已经工作完成,主线程可以退出.
请排查该原型代码中的错误.
代码五:
考察考生对正则表达式的理解和运用.
正则表达式:
邮件地址:name@domain,其中name和domain部分,只能出现大小写字母,点(.)以及下划线(_),
请写出一个正则表达式能够取出name部分和domain部分分组.
举例:zheng.cuizh@gmail.com
能够取到zheng.cuizh以及gmail.com
如果地址中有非法字符,则不继续匹配.
match中的参数是答案
>> mail="zheng.cuizh@gmail.com"
=> "zheng.cuizh@gmail.com"
>> mail.match(/^([a-zA-Z0-9\.\_]*)?\@([a-zA-Z0-9\.\_]*\.[a-zA-Z0-9\.\_]*)$/)
=> #<MatchData "zheng.cuizh@gmail.com" 1:"zheng.cuizh" 2:"gmail.com">
>> mail.match(/^([a-zA-Z0-9\.\_]*)?@([a-zA-Z0-9\.\_]*\.[a-zA-Z0-9\.\_]*)$/)
=> #<MatchData "zheng.cuizh@gmail.com" 1:"zheng.cuizh" 2:"gmail.com">
>> mail.match(/^([a-zA-Z0-9\.\_]*)@([a-zA-Z0-9\.\_]*\.[a-zA-Z0-9\.\_]*)$/)
=> #<MatchData "zheng.cuizh@gmail.com" 1:"zheng.cuizh" 2:"gmail.com">
代码六:
这段代码考察考生在做字符串操作的时候是否考虑越界.
这段代码是测试rpc_call方法在执行若干次后是否出错的代码,rpc_call这个函数需要在每次调用的时候使用一个唯一的id,这个id我们通过uuid方法获得.但该段代码存在一个错误,请找出.
int rpc_call(char *);
char* uuid();
int caller()
{
char name[32];
int i = 100;
while(i--)
{
//sprintf(name,"%s",uuid);
//or
//memset(name,0,16);
strcat(name,uuid());
syslog(LOG_ERR,"current name is => %s",name);
rpc_call(name);
}
}
代码七:
下面这段代码考察考生对位运算的理解.
long generate();
unsigned long l = generate();
下面这个运算起到什么作用?
l<<1;
l>>1;
下面这个运算起到什么作用?
l&=0xfffffffe
代码八:
下面这个题目考察考生对异常处理底层实现的理解.
请使用setjmp.h中的方法实现C的异常处理.
#include <setjmp.h>
jmp_buf jb;
int ret = setjmp(jb);
switch(ret)
{
case 0:/*ok*/;break;
case 1:exc1_handler();break;
case 2:exc2_handler();break;
default:default_handler();
}
if(a==b){/*do ok*/}
else{/*raise exception*/longjmp(jb,1)}