C语言自定义_strdup复制字符串 free时触发invalid pointer报错
自定义
_strdup函数free触发无效指针问题排查 问题现象
尝试实现自定义_strdup函数完成字符串复制功能,完整代码如下:
#include <stdlib.h> #include <stdio.h> char *_strdup(char *str); /** * main - Entry point of my program * * Return: Always 0. */ int main(void) { char *s; s = _strdup("Copied String"); if (s == NULL) { printf("failed to allocate memory\n"); return (1); } printf("%s\n", s); free(s); return (0); } /** * _strdup - This function returns a pointer to a new string * which is a duplicate of the string str * * @str: The string to be copied * * Return: On Success, this function returns a pointer to * the duplicated string. It returns NULL, if insufficent * memory was avaliable, and if str == NULL. */ char *_strdup(char *str) { char *ch; if (str == NULL) { return (NULL); } ch = malloc(sizeof(*ch) * sizeof(*str)); ch = str; return (ch); }
程序运行后可以正常输出目标字符串,但执行free操作时抛出如下错误:
Copied String free(): invalid pointer Aborted (core dumped)
错误原因
代码存在3个核心问题,直接触发报错:
- 指针被非法覆盖:调用
malloc申请堆内存后,执行ch = str;直接把ch保存的堆地址覆盖为入参字符串的地址。传入的"Copied String"是存储在只读数据段的字符串常量,不属于malloc分配的堆内存,对非堆地址调用free必然触发无效指针错误。同时之前申请的堆内存因为地址丢失,已经产生了不可回收的内存泄漏。 - 内存分配大小计算错误:
sizeof(*ch)和sizeof(*str)都是char类型的大小,固定为1,sizeof(*ch) * sizeof(*str)计算结果仅为1字节,完全不足以存储完整字符串,就算指针不被覆盖,后续复制操作也会触发缓冲区溢出。 - 未实现实际的复制逻辑:代码没有把原字符串的内容写入新申请的内存,之前能正常打印字符串,只是因为指针直接指向了原常量字符串,根本没有完成“复制新字符串”的预期功能。
修复方案
修正_strdup的实现逻辑,按照标准流程完成字符串复制:
- 校验入参合法性,入参为NULL时直接返回NULL
- 计算原字符串长度,申请堆内存时额外多分配1字节用于存储字符串结束符
\0 - 校验
malloc返回值,处理内存分配失败的场景 - 逐字节将原字符串内容复制到新申请的堆内存中,手动补充结束符
- 返回堆内存的原始地址,不要修改指针指向
修复后的完整_strdup实现如下,需要额外引入<string.h>头文件支持strlen调用:
#include <string.h> char *_strdup(char *str) { char *ch; size_t str_len; size_t i; if (str == NULL) { return (NULL); } str_len = strlen(str); // 分配长度为字符串长度+1,预留结束符空间 ch = malloc(sizeof(char) * (str_len + 1)); if (ch == NULL) { return (NULL); } // 逐字符复制内容 for (i = 0; i < str_len; i++) { ch[i] = str[i]; } ch[i] = '\0'; return (ch); }
修复后返回的指针是malloc合法分配的堆地址,存储了独立于原字符串的完整副本,调用free可以正常释放内存,不会触发报错。
内容的提问来源于stack exchange,提问作者Leuel Asfaw
相关产品推荐
相关产品推荐

