c语言面试试题及答案.docx
- 文档编号:23849785
- 上传时间:2023-05-21
- 格式:DOCX
- 页数:9
- 大小:16.91KB
c语言面试试题及答案.docx
《c语言面试试题及答案.docx》由会员分享,可在线阅读,更多相关《c语言面试试题及答案.docx(9页珍藏版)》请在冰豆网上搜索。
c语言面试试题及答案
c语言面试试题及答案
问:
请找出下面代码里的问题:
#include
intmain(void)
{
charbuff[10];
memset(buff,0,sizeof(buff));
gets(buff);
printf("Thebufferenteredis[%s]",buff);
return0;
}
答:
上面代码里的问题在于函数gets()的使用,这个函数从stdin接收一个字符串而不检查它所复制的缓存的容积,这可能会导致缓存溢出。
这里推荐使用标准函数fgets()代替。
问:
下面是一个简单的密码保护功能,你能在不知道密码的情况下将其破解吗?
#include
intmain(intargc,char*argv[])
{
intflag=0;
charpasswd[10];
memset(passwd,0,sizeof(passwd));
strcpy(passwd,argv[1]);
if(0==strcmp("LinuxGeek",passwd))
{
flag=1;
}
if(flag)
{
printf("Passwordcracked");
}
else
{
printf("Incorrectpasswd");
}
return0;
}
答:
破解上述加密的关键在于利用攻破strcpy()函数的漏洞。
所以用户在向“passwd”缓存输入随机密码的时候并没有提前检查“passwd”的容量是否足够。
所以,如果用户输入一个足够造成缓存溢出并且重写“flag”变量默认值所存在位置的内存的长“密码”,即使这个密码无法通过验证,flag验证位也变成了非零,也就可以获得被保护的数据了。
例如:
$./psswdaaaaaaaaaaaaa
Passwordcracked
虽然上面的密码并不正确,但我们仍然可以通过缓存溢出绕开密码平安保护。
要防止这样的问题,建议使用strncpy()函数。
作者注:
最近的编译器会在内部检测栈溢出的可能,所以这样往栈里存储变量很难出现栈溢出。
在我的g里默认就是这样,所以我不得不使用编译命令‘-fno-stack-protector’来实现上述方案。
问:
下面的代码能编译通过吗?
如果能,它有什么潜在的问题吗?
#include
voidmain(void)
{
char*ptr=(char*)malloc(10);
if(NULL==ptr)
{
printf("Mallocfailed");
return;
}
else
{
//Dosomeprocessing
free(ptr);
}
return;
}
答:
因为main()方法的返回类型,这段代码的错误在大多数编译器里会被当作警告。
main()的返回类型应该是“int”而不是“void”。
因为“int”返回类型会让程序返回状态值。
这点非常重要,特别当程序是作为依赖于程序成功运行的脚本的一部分运行时。
问:
下面的代码会导致内存泄漏吗?
#include
voidmain(void)
{
char*ptr=(char*)malloc(10);
if(NULL==ptr)
{
printf("Mallocfailed");
return;
}
else
{
//Dosomeprocessing
}
return;
}
答:
尽管上面的代码并没有释放分配给“ptr”的内存,但并不会在程序退出后导致内存泄漏。
在程序完毕后,所有这个程序分配的内存都会自动被处理掉。
但如果上面的代码处于一个“while循环”中,那将会导致严重的内存泄漏问题!
提示:
如果你想知道更多关于内存泄漏的知识和内存泄漏检测工具,可以来看看我们在Valgrind上的文章。
问:
下面的程序会在用户输入’freeze’的时候出问题,而’zebra’那么不会,为什么?
#include
intmain(intargc,char*argv[])
{
char*ptr=(char*)malloc(10);
if(NULL==ptr)
{
printf("Mallocfailed");
return-1;
}
elseif(argc==1)
{
printf("Usage");
}
else
{
memset(ptr,0,10);
strncpy(ptr,argv[1],9);
while(*ptr!
='z')
{
if(*ptr=='')
break;
else
ptr++;
}
if(*ptr=='z')
{
printf("Stringcontains'z'");
//Dosomemoreprocessing
}
free(ptr);
}
return0;
}
答:
这里的问题在于,代码会(通过增加“ptr”)修改while循环里“ptr”存储的地址。
当输入“zebra”时,while循环会在执行前被终止,因此传给free()的变量就是传给malloc()的地址。
但在“freeze”时,“ptr”存储的地址会在while循环里被修改,因此导致传给free()的地址出错,也就导致了seg-fault或者崩溃。
问:
在下面的代码中,atexit()并没有被调用,为什么?
#include
voidfunc(void)
{
printf("Cleanupfunctioncalled");
return;
}
intmain(void)
{
inti=0;
atexit(func);
for(;i<0xffffff;i++);
exit(0);
}
这是因为exit()函数的使用,该函数并没有调用atexit()等函数清理。
如果使用atexit()就应当使用exit()或者“return”与之相配合。
问:
你能设计一个能承受任何类型的参数并返回interger(整数)结果的函数吗?
答:
如下:
intfunc(void*ptr)
如果这个函数的参数超过一个,那么这个函数应该由一个构造体来调用,这个构造体可以由需要传递参数来填充。
问:
下面的操作会输出什么?
为什么?
#include
intmain(void)
{
char*ptr="Linux";
printf("[%c]",*ptr++);
printf("[%c]",*ptr);
return0;
}
答:
输出结果应该是这样:
[L]
[i]
因为“++”和“*”的优先权一样,所以“*ptr++”相当于“*(ptr++)”。
即应该先执行ptr++,然后才是*ptr,所以操作结果是“L”。
第二个结果是“i”。
问:
下面的代码段有错,你能指出来吗?
#include
intmain(void)
{
char*ptr="Linux";
*ptr='T';
printf("[%s]",ptr);
return0;
}
答:
这是因为,通过*ptr=‘T’,会改变内存中代码段(只读代码)“Linux”的第一个字母。
这个操作是无效的,因此会造成seg-fault或者崩溃。
问:
你能写出一个在运行时改变自己进程名的程序吗?
答:
参见下面这段代码:
#include
intmain(intargc,char*argv[])
{
inti=0;
charbuff[100];
memset(buff,0,sizeof(buff));
strncpy(buff,argv[0],sizeof(buff));
memset(argv[0],0,strlen(buff));
strncpy(argv[0],"NewName",7);
//Simulateawait.Checktheprocess
//nameatthispoint.
for(;i<0xffffffff;i++);
return0;
}
问:
下面代码有问题吗?
如果有,该怎么修改?
#include
int*inc(intval)
{
inta=val;
a++;
return&a;
}
intmain(void)
{
inta=10;
int*val=inc(a);
printf("Incrementedvalueisequalto[%d]",*val);
return0;
}
答:
尽管上面的程序有时候能够正常运行,但是在“inc()”中存在严重的漏洞。
这个函数返回本地变量的地址。
因为本地变量的生命周期就是“inc()”的生命周期,所以在inc完毕后,使用本地变量会发生结果。
这可以通过将main()中变量“a”的地址来防止,这样以后还可以修改这个地址存储的值。
问:
下面代码会输出什么?
#include
intmain(void)
{
inta=10,b=20,c=30;
printf("%d..%d..%d",a+b+c,(b=b*2),(c=c*2));
return0;
}
答:
输出结果是:
110..40..60
这是因为C语言里函数的参数默认是从右往左处理的,输出时是从左往右。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 语言 面试 试题 答案