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

自定义strncat()函数触发Stack smashing detected错误的原因及修复

自定义_strncat函数栈溢出错误的原因与修复

我编写的代码旨在复刻strncat()函数的功能,代码能输出预期结果,但始终会出现“Stack smashing detected (Aborted Core Dump)”错误,需排查错误原因并找到修复方法。

代码文件

main.h

#ifndef MAIN_H
#define MAIN_H

#include <stdio.h>
#include <string.h>

int _putchar(char c);
char *_strcat(char *dest, char *src);
char *_strncat(char *dest, char *src, int n);

#endif

1-main.c

#include "main.h"
#include <stdio.h>

/**
 * main - check the code
 *
 * Return: Always 0.
 */

int main(void)
{
        char s1[98] = "Hello ";
        char s2[] = "World!\n";
        char *ptr;

        printf("%s\n", s1);
        printf("%s", s2);
        ptr = _strncat(s1, s2, 1);
        printf("%s\n", s1);
        printf("%s", s2);
        printf("%s\n", ptr);
        ptr = _strncat(s1, s2, 1024);
        printf("%s", s1);
        printf("%s", s2);
        printf("%s", ptr);
        return (0);
}

1-strncat.c(原错误实现)

#include "main.h"

/**
 * _strncat - Concatenates strings
 * @dest: destination string
 * @src: source string
 * @n: Max bytes
 * Return: dest
 */

char *_strncat(char *dest, char *src, int n)
{
        int srclen = 0;
        int destlen = 0;
        int i = 0;
        int j = 0;

        while (src[srclen] != '\0')
        {
                srclen++;
        }
        while (dest[destlen] != '\0')
        {
                destlen++;
        }
        for (i = destlen; (i < (destlen + n) && j < n); i++)
        {
                dest[i] = src[j];
                j++;
        }
        dest[destlen + n] = '\0';
        return (dest);
}

错误原因分析

  1. 终止符写入越界:
    代码最后一行dest[destlen + n] = '\0';是核心问题。无论src实际有多少字符,也不管dest剩余空间是否足够,直接在destlen + n位置写入终止符。比如main函数中第二次调用_strncat时传入n=1024,此时destlen加上1024远远超过s1数组的98字节容量,直接破坏栈内存,触发栈溢出检测。

  2. 循环未处理src提前结束的情况:
    原循环条件只限制了拷贝次数不超过n,但没有判断src[j]是否已到字符串结束符'\0'。如果src长度小于n,代码仍会尝试拷贝n个字符,可能读取src数组外的未知内存,同时后续写入终止符的位置也会错误。

  3. 冗余的长度计算:
    提前计算srclen完全没必要,既浪费性能,也没用到这个值做有效判断。


修复方法及代码

针对上述问题,修改后的_strncat实现如下:

#include "main.h"

/**
 * _strncat - Concatenates strings
 * @dest: destination string
 * @src: source string
 * @n: Max bytes to copy from src
 * Return: Pointer to dest
 */

char *_strncat(char *dest, char *src, int n)
{
    int dest_len = 0;
    int copy_count = 0;

    // 定位dest的末尾
    while (dest[dest_len] != '\0')
    {
        dest_len++;
    }

    // 最多拷贝n个字符,直到src结束
    while (copy_count < n && src[copy_count] != '\0')
    {
        dest[dest_len + copy_count] = src[copy_count];
        copy_count++;
    }

    // 在实际拷贝的字符末尾添加终止符
    dest[dest_len + copy_count] = '\0';

    return dest;
}

修复要点说明

  • 移除冗余的srclen计算,改为在循环中实时判断src是否到达结束符,避免无效计算和内存越界读取。
  • 终止符写入位置改为dest_len + copy_count,即实际拷贝字符的下一位,确保不会超出dest的有效范围(只要调用者保证dest有足够空间,比如main中的s1[98])。
  • 使用更简洁的while循环替代for循环,逻辑更清晰,同时覆盖了src长度小于n的场景。

内容的提问来源于stack exchange,提问作者Akintola Oluwaseyi Alex

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 15:58:21