ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Coursebook C字符串深度指南:从strlen(s)+1到内存分配

Coursebook C字符串深度指南:从strlen(s)+1到内存分配 Coursebook C字符串深度指南从strlen(s)1到内存分配【免费下载链接】coursebookOpen Source Introductory Systems Programming Textbook for the University of Illinois项目地址: https://gitcode.com/GitHub_Trending/co/coursebookCoursebook 是一本面向新手的开源系统编程教材University of Illinois 出品本指南带你吃透C字符串最核心的坑为什么存储一个字符串必须准备strlen(s)1个字节以及如何正确完成C内存分配malloc 与 NUL 终止符的关系一次避免缓冲区溢出这类经典错误。为什么C字符串要1NUL终止符的由来C语言采用NUL终止字符串Null Terminated而非长度前缀字符串一串字节末尾跟一个\00x00字节表示到此为止。 核心结论字符串Hi需要 3 个字节——[H] [i] [\0]。写法含义实际占用Hi2个字符 1个NUL3 字节ABC3个字符 1个NUL4 字节由于没有长度字段唯一的办法就是一直读内存直到遇到NUL字节——这也是strlen()的工作原理从头往后数遇到\0停手返回的计数不包含NUL 本身。 忘记 NUL 终止的后果读取会越界扫到相邻内存轻则输出乱码重则触发段错误SEGFAULT或像 Heartbleed 一样的安全漏洞。经典错误malloc(strlen(input)) 差的那一个字节教材在 introc/common_bugs.tex 中专门设了一节《Strings require strlen(s)1 bytes》用strdup实现演示了三种分配方式copy malloc(sizeof(char*)); /* 错只分配了指针大小 */ copy malloc(strlen(input)); /* 差一点……NUL放不下了*/ copy malloc(strlen(input) 1); /* 正确写法 */第一个错误sizeof(char*)分配的是指针的空间通常 8 字节不是字符串的空间短字符串时侥幸能跑长字符串立刻踩坏内存。第二个错误strlen(input)恰好是可见字符数没有 NUL 的位置。后续strcpy写入终止符时会越界写 1 字节破坏堆上相邻块。正确做法永远是strlen(s) 1。这条差一错误在教材的 review/review.tex 练习题中还被反复考——malloc(strlen(src))是新手必错点。图示堆块被拆分的过程来自 malloc/malloc.tex。malloc(strlen(s)1)时分配器正是从某个空闲块中切出刚好够用的空间——如果少算 1 字节你的 NUL 终止符就写进了下一个块的元数据。内存分配实战first fit 是怎么找到你的字符串的当你调用malloc(strlen(s)1)分配器会在堆里找一块足够大的空闲块。教材 malloc/malloc.tex 介绍了三大放置策略其中first fit首次适应最常用从头扫描遇到第一个够大的洞就切下来用。图示first fit 策略把一个 16KiB 空闲块切成 2KiB给请求用 14KiB 剩余空闲块。你的字符串连同 NUL 就安放在切出的小块里。对应的反面教材是分配不足under-allocation在 introc/common_bugs.tex 中用malloc(sizeof(user))指针大小 8 字节去装一个 100 字节的结构体一写就溢出。记住口诀要存什么就分配什么的大小存字符串永远 1。释放与合并free 时的 double coalesce字符串用完要free。如果这块内存前后恰好都是空闲块分配器会做double coalesce双向合并把三段拼成一个更大的空闲块防止堆碎片化。图示free()一个被使用块后它与前后空闲空间合并成一块新的大空闲区来自 malloc/malloc.tex。⚠️ 释放后请把指针置为NULL避免悬垂指针再次读写那块内存——这是 introc/common_bugs.tex 里 Double Frees 一节的重点。常用字符串函数速查与安全建议以下函数都声明在string.h中详解见 introc/common_c_functions.tex函数作用注意点strlen(s)返回字符串长度结果不含 NULstrlen(NULL)是未定义行为strcpy(d, s)拷贝字符串要求目标空间足够否则未定义行为strcat(d, s)拼接字符串要求尾部含 NUL 在内都放得下strdup(s)malloc 一份副本内部自动按strlen1分配strcmp(a, b)比较字典序只用符号判断0 / 0 / 0安全三原则新手务必养成分配缓冲区一律按最坏长度 1计算如路径拼接场景char newpath[strlen(path) strlen(name) 1];参考 filesystems/filesystems.tex打印到字符串优先snprintf/asprintf它们天然不会溢出见 introc/common_c_functions.tex用fgets、getline替代已废弃的gets输入长度永远可控。延伸阅读教材里的相关章节字符串存放位置与字面量只读性introc/c_memory_model.tex常见 Bug 全集NUL字节、双释放、缓冲区溢出introc/common_bugs.tex分配器完整实现堆、sbrk、free 列表malloc/malloc.tex字符串练习题手写 strlen、strcatreview/review.tex 一句话总结在C语言里字符串长度永远是strlen(s) 1字节——多出来的那 1 字节是程序不崩溃的最后一道保险。【免费下载链接】coursebookOpen Source Introductory Systems Programming Textbook for the University of Illinois项目地址: https://gitcode.com/GitHub_Trending/co/coursebook创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表