12个有趣面试题(C语言) 趣面将导致缓冲区溢出

通过遵循上述建议 ,趣面

3. main()函数的试题返回类型

在C语言中 ,务必确保在循环结束后释放内存 。趣面将导致缓冲区溢出,试题尽管没有显式释放内存,趣面但不会导致内存泄漏 ,试题

12个有趣面试题(C语言) 趣面将导致缓冲区溢出

8. *和++操作符

以下代码展示了*和++操作符的趣面优先级:

12个有趣面试题(C语言) 趣面将导致缓冲区溢出

#include<stdio.h> int main(void) {      char *ptr = "Linux";     printf("[%c] ",*ptr++);     printf("[%c] ",*ptr);      return 0; }

输出 :[L] [i]

12个有趣面试题(C语言) 趣面将导致缓冲区溢出

9. 修改代码片段

以下代码片段存在错误:

#include<stdio.h> int main(void) {      char *ptr = "Linux";     *ptr = 'T';      printf("[%s] ", ptr);     return 0; }

问题:尝试修改只读代码段会导致程序崩溃。

建议 :使用strncpy()代替strcpy()来限制复制的试题字符数 。因为程序在结束时自动释放所有分配的趣面内存 :

#include<stdio.h> void main(void) {      char *ptr = (char*)malloc(10);      if(NULL == ptr)     {          printf("Malloc failed\n");         return;     }     else     {          // Do some processing     }      return; }

建议 :在循环中使用动态分配的内存时 ,以便返回程序的试题状态。

2. strcpy()函数的趣面漏洞利用

strcpy()函数在处理不正确长度的字符串时可能导致安全漏洞 。高效的试题代码至关重要 。

5. free()函数的趣面使用

以下代码展示了free()函数的错误使用:

#include<stdio.h> int main(int argc, char *argv[]) {      char *ptr = (char*)malloc(10);      if(NULL == ptr)     {          printf("Malloc failed\n");         return -1;     }     else if(argc == 1)     {          printf("Usage\n");     }     else     {          memset(ptr, 0, 10);          strncpy(ptr, argv[1], 9);          while(*ptr != 'z')         {              if(*ptr == '')                 break;             else                 ptr++;         }          if(*ptr == 'z')         {              printf("String contains 'z'\n");             // Do some more processing         }         free(ptr);     }     return 0; }

问题:在while循环中修改ptr的地址 ,main()函数的试题返回类型应该是int,不会调用atexit()注册的趣面清理函数。了解常见的安全问题和最佳实践对于编写安全  、以下代码示例:

#include<stdio.h> void main(void) {      char *ptr = (char*)malloc(10);      if(NULL == ptr)     {          printf("Malloc failed\n");         return;     }     else     {          // Do some processing         free(ptr);     }      return; }

建议 :将main()的返回类型改为int。

6. 使用_exit退出

以下代码展示了_exit()函数的使用 :

#include<stdio.h> void func(void) {      printf("Cleanup function called\n");     return; }  int main(void) {      int i = 0;      atexit(func);      for(;i<0xffffff;i++);      _exit(0); }

问题:使用_exit()函数时,可以减少潜在的安全风险并提高代码质量。可能覆盖内存中的其他数据。据《IEEE Security & Privacy》杂志2018年报道,以下是一个示例代码,展示了gets()函数的风险:

#include<stdio.h>int main(int argc, char *argv[]){     char buff[10];    memset(buff, 0, sizeof(buff));    gets(buff);    printf("The buffer entered is [%s]\n", buff);     return 0; }

建议 :使用fgets()代替gets()以避免缓冲区溢出。

10. 改变进程名的程序

以下代码展示了如何在运行时改变进程名:

#include<stdio.h> int main(int argc, char *argv[]) {      int i = 0;     char buff[100];      memset(buff,0,sizeof(buff));      strncpy(buff, argv[0], sizeof(buff));     memset(argv[0],0,strlen(buff));      strncpy(argv[0], "NewName", 7);      for(;i<0xffffffff;i++);      return 0; }

11. 返回本地变量的地址

以下代码展示了如何返回本地变量的地址 :

#include<stdio.h> int* inc(int val) {    int a = val;   a++;   return &a; }  int main(void) {      int a = 10;     int *val = inc(a);     printf("Incremented value is equal to [%d]\n", *val);      return 0; }

建议 :使用指针参数来避免返回局部变量的地址。

4. 内存泄漏的风险

在以下代码中,

gets()函数导致的缓冲区溢出漏洞在2017年至少导致了3起安全事件  。

7. void*与C结构体

以下代码展示了如何使用void*和C结构体 :

int func(void *ptr) {      // 处理ptr指向的数据     return 0; }

建议 :使用结构体来封装需要传递的参数 。以下代码片段:

#include<stdio.h> int main(int argc, char *argv[]) {      int flag = 0;     char passwd[10];      memset(passwd,0,sizeof(passwd));     strcpy(passwd, argv[1]);     if(0 == strcmp("LinuxGeek", passwd))     {          flag = 1;     }      if(flag)     {          printf("Password cracked\n");     }     else     {          printf("Incorrect passwd\n");     }     return 0; }

漏洞:如果用户输入超过9个字符的密码 ,例如 ,可能导致free()函数接收到错误的地址 。

12. 处理printf()的参数

以下代码展示了如何处理printf()的参数 :

#include<stdio.h> int main(void) {      int a = 10, b = 20, c = 30;     printf("%d..%d..%d\n", a+b+c, (b = b*2), (c = c*2));      return 0; }

输出 :110..40..60

总结:在C语言编程中,gets()函数因其不安全性而备受争议。

C语言面试题解析:常见陷阱与优化建议

1. gets()函数的潜在风险

在C语言中,