You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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的实现逻辑,按照标准流程完成字符串复制:

  1. 校验入参合法性,入参为NULL时直接返回NULL
  2. 计算原字符串长度,申请堆内存时额外多分配1字节用于存储字符串结束符\0
  3. 校验malloc返回值,处理内存分配失败的场景
  4. 逐字节将原字符串内容复制到新申请的堆内存中,手动补充结束符
  5. 返回堆内存的原始地址,不要修改指针指向
    修复后的完整_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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 12:31:01