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

重写strcat函数遇二级指针打印NULL及段错误,求修复方案

修复自定义my_strcat的段错误与NULL输出问题

核心错误点

  • 参数类型与传递完全错误:main函数里的str是栈上固定大小的数组,你强制将其转为char**传递给my_strcat属于严重类型违规。栈数组的地址不可修改,也不能用realloc扩容,且强制转换后会把字符串第一个字符的ASCII值当作指针地址,直接触发非法内存访问。
  • my_strlen调用逻辑错误:my_strlen((char *)dest)是把char**类型的指针直接转成char*,相当于把指针本身的内存内容当成字符串,完全无法获取目标字符串的真实长度,正确写法应为my_strlen(*dest)(*dest才是指向目标字符串的指针)。
  • realloc使用错误:你修改的是函数形参dest,而非外部传入的指针本身,且realloc的第一个参数应为原堆指针(即*dest)而非dest。修改形参不会影响外部变量,必须将realloc的返回值赋值给*dest,同时要检查分配是否成功。
  • 指针优先级与赋值错误:*dest[count]的优先级逻辑错误,[]比*优先级高,实际会解析为*(dest[count]),正确写法是(*dest)[count];最后添加终止符的*dest[count] += '\0'是错误操作,应直接赋值为'\0'。

修复后的代码(动态扩容版本)

该版本支持自动扩容,要求目标字符串为堆分配内存:

#include <stdlib.h>
#include <stdio.h>
#include <string.h> // 用于strcpy初始化堆字符串
#ifndef MY_STRING_H
#define MY_STRING_H

int my_strlen(const char *str) {
    int count;
    for (count = 0; str[count] != '\0'; ++count);
    return count; 
}

// dest必须是指向堆分配char指针的指针,禁止传入栈数组
void my_strcat(char **dest, const char *src) {
    if (dest == NULL || *dest == NULL || src == NULL) {
        return; // 空指针边界检查
    }

    size_t srcSize = my_strlen(src);
    size_t destSize = my_strlen(*dest);
    // 分配内存时要额外+1存储字符串终止符
    char *newDest = realloc(*dest, destSize + srcSize + 1);
    if (newDest == NULL) {
        perror("realloc failed");
        return;
    }
    *dest = newDest; // 更新外部的指针地址

    // 定位目标字符串末尾
    int count;
    for (count = 0; (*dest)[count] != '\0'; ++count);
    // 复制源字符串内容
    for (int count2 = 0; src[count2] != '\0'; ++count2) {
        (*dest)[count] = src[count2];
        count++;
    }
    (*dest)[count] = '\0'; // 添加字符串终止符
}

int main (){
    // 使用堆分配字符串,栈数组无法支持realloc扩容
    char *str = malloc(80);
    if (str == NULL) {
        perror("malloc failed");
        return 1;
    }
    strcpy(str, "these strings"); // 初始化堆字符串

    my_strcat(&str, "are ");
    my_strcat(&str, "concatenated.");
    printf("%s\n", str);

    free(str); // 释放堆内存,避免泄漏
    return 0;
}

#endif // MY_STRING_H

标准库风格实现(固定缓冲区版本)

如果要复刻标准strcat的逻辑(要求目标缓冲区有足够预分配空间),无需二级指针和realloc:

#include <stdio.h>
#ifndef MY_STRING_H
#define MY_STRING_H

int my_strlen(const char *str) {
    int count;
    for (count = 0; str[count] != '\0'; ++count);
    return count; 
}

// 标准strcat实现:要求dest有足够容纳拼接后内容的空间
void my_strcat(char *dest, const char *src) {
    if (dest == NULL || src == NULL) {
        return;
    }
    // 定位目标字符串末尾
    char *d = dest;
    while (*d != '\0') {
        d++;
    }
    // 复制源字符串
    while (*src != '\0') {
        *d = *src;
        d++;
        src++;
    }
    *d = '\0';
}

int main() {
    char str[80] = "these strings";
    my_strcat(str, "are ");
    my_strcat(str, "concatenated.");
    printf("%s\n", str);
    return 0;
}

#endif // MY_STRING_H

内容的提问来源于stack exchange,提问作者Bot Ellis

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 08:30:36