当前位置: 首页 > news >正文

10道经典C语言面试题解析与安全实践

10道经典C语言面试题深度解析

1. 项目概述

本文精选10道具有代表性的C语言面试题,涵盖指针操作、内存管理、函数设计等核心知识点。这些题目来自实际工程面试场景,能够有效检验开发者对C语言底层机制的理解程度。

2. 题目解析

2.1 gets()函数的安全隐患

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

问题分析

  • gets()函数不检查输入缓冲区大小,当输入超过9个字符(含结尾的'\0')时会导致缓冲区溢出
  • 这种溢出可能破坏栈结构,导致程序崩溃或被恶意利用

解决方案

fgets(buff, sizeof(buff), stdin);

fgets()会限制读取的字符数,确保不超过缓冲区容量

2.2 strcpy()函数的安全漏洞

#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; }

漏洞原理

  • strcpy()同样不检查目标缓冲区大小
  • 通过输入超长字符串可以覆盖flag变量的内存空间
  • 即使密码错误,也能通过溢出修改flag值绕过验证

安全实践

strncpy(passwd, argv[1], sizeof(passwd)-1); passwd[sizeof(passwd)-1] = '\0';

2.3 main()函数的返回值规范

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

规范问题

  • main()应返回int类型,表示程序退出状态
  • 返回0表示成功,非0值表示错误类型
  • 这种规范对脚本调用和自动化测试非常重要

修正方案

int main(void) { /* ... */ return 0; }

2.4 内存泄漏场景分析

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

关键点

  • 单次运行不会造成持久性内存泄漏
  • 操作系统会在进程结束时回收所有内存
  • 但在循环或长期运行的服务中会导致严重问题

最佳实践

free(ptr); // 在return前释放内存

2.5 指针移动导致的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"); } free(ptr); } return 0; }

问题根源

  • ptr在while循环中被修改
  • free()必须使用malloc()返回的原始地址
  • 修改后的ptr会导致段错误(Segmentation Fault)

解决方案

char *original_ptr = ptr; // ...操作ptr... free(original_ptr);

2.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()会调用atexit()注册的函数
  • _exit()直接终止进程,不执行清理
  • 在需要资源释放时应使用exit()

2.7 通用函数接口设计

需求:设计接受任意类型参数并返回整数的函数

解决方案

int func(void *ptr)

通过void*指针接收任意数据类型,配合结构体可传递多个参数

2.8 指针运算优先级

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

运算规则

  • 后缀++优先级高于解引用*
  • ptr++等价于(ptr++)
  • 因此先返回*ptr,再执行ptr++

2.9 字符串常量修改问题

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

根本原因

  • 字符串常量存储在只读数据段
  • 通过指针修改会导致段错误
  • 应使用字符数组存储可修改字符串

正确写法

char ptr[] = "Linux";

2.10 返回局部变量地址

#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; }

问题分析

  • 函数返回局部变量的地址
  • 局部变量在函数返回后生命周期结束
  • 访问该地址会导致未定义行为

解决方案

int *inc(int val, int *result) { *result = val + 1; return result; }

3. 工程实践建议

  1. 安全函数选择

    • 优先使用带长度检查的函数(fgets、strncpy等)
    • 避免使用不安全的传统函数(gets、strcpy等)
  2. 内存管理原则

    • 确保每个malloc()都有对应的free()
    • 使用工具(如Valgrind)检测内存泄漏
  3. 指针操作规范

    • 避免修改malloc()返回的原始指针
    • 对指针运算保持高度警惕
  4. 函数设计准则

    • main()必须返回int类型
    • 不返回局部变量的地址或引用
  5. 字符串处理

    • 区分字符串常量和字符数组
    • 修改字符串内容应使用字符数组
http://www.jsqmd.com/news/546661/

相关文章:

  • Three.js实战:解决CSS2DObject点击事件失效的3种方法(附完整代码)
  • 3步掌握TikTok Shop API PHP SDK实战开发指南
  • Vue 2 中文文档:连接全球技术与中文开发者的桥梁
  • [ADS] 谐波平衡仿真与时频域波形分析实战
  • 单片机编程框架技术解析与应用指南
  • DLT Viewer诊断工具零基础入门:从安装到日志分析的效率提升指南
  • 告别台式机?用闲置笔记本M.2口给FPGA开发板‘开个后门’做PCIE验证
  • 电感啸叫分析与DC-DC转换器降噪方案
  • 终极指南:使用PHP高效对接TikTok Shop电商API
  • 达梦数据库安装后必做的5件事:验证、连接、基础配置与安全加固
  • 2026婺城区皮肤病诊疗机构选择白皮书:开发区皮肤科/金华市皮肤病/金华市皮肤科/金华皮肤病/金华皮肤科/选择指南 - 优质品牌商家
  • OpenClaw数据整理术:Qwen3.5-9B智能归类CSV与Markdown文件
  • 智能抠像:开源OBS插件实现实时背景处理的完整指南
  • 【经验贴】考过CDA数据分析师二级,从旅游业业务岗转行数据分析师
  • 2026河北电动门厂商综合实力榜:五大品牌深度解析与选型指南 - 2026年企业推荐榜
  • 嵌入式C语言高效编程的三项核心技能
  • 微信个人号机器人开发框架:从入门到企业级应用指南
  • 2026广州电脑维修服务深度评测报告 - 优质品牌商家
  • 足球场精准定位技术:从计算机视觉到智能体育分析的实践指南
  • Gitee开源智能体项目
  • FeignClient调用报400?可能是你的SpringBoot 3.3.0微服务在偷偷初始化腾讯云IM
  • 2026义乌智能玩具机芯服务商五强揭晓:沃芯科技领跑情感交互新赛道 - 2026年企业推荐榜
  • Ruby 在 2026 年构建 AI 智能体的最佳目标语言
  • 2026文武兼修优质武校推荐指南 - 优质品牌商家
  • 告别卡顿!用BK7259这颗WiFi6芯片,给你的智能门锁和IP摄像头做个‘心脏移植’
  • OpenLayers 实战:用 ol-ext 的 Mask 和 Crop 滤镜实现地图区域高亮(附完整代码与偏移问题修复)
  • 类器官原代培养无菌预防及细胞房除菌攻略
  • 做了5年GEO优化,我敢说90%的企业都没看懂GEO的真实成本
  • 技术扎实、就业有保障:2026年南宁靠谱美甲培训选择指南 - 2026年企业推荐榜
  • 重庆医疗纠纷律师专业评测:2026年五大实力律所深度解析 - 2026年企业推荐榜