#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
如果地址中有非法字符,則不繼續匹配.
match中的參數是答案
>> mail="[email protected]"
=> "[email protected]"
>> mail.match(/^([a-zA-Z0-9\.\_]*)?\@([a-zA-Z0-9\.\_]*\.[a-zA-Z0-9\.\_]*)$/)
=> #<MatchData "[email protected]" 1:"zheng.cuizh" 2:"gmail.com">
>> mail.match(/^([a-zA-Z0-9\.\_]*)?@([a-zA-Z0-9\.\_]*\.[a-zA-Z0-9\.\_]*)$/)
=> #<MatchData "[email protected]" 1:"zheng.cuizh" 2:"gmail.com">
>> mail.match(/^([a-zA-Z0-9\.\_]*)@([a-zA-Z0-9\.\_]*\.[a-zA-Z0-9\.\_]*)$/)
=> #<MatchData "[email protected]" 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)}