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

将char数组传入void指针出现异常行为的原因排查

自定义strcpy指针实现的地址偏移问题分析

问题现象

实现自定义strcpy时,采用指针递增赋值的方案出现未预期行为:复制过程的中间打印显示字符赋值正常,但最终打印的内存地址和对应值不符合预期,无法正确输出目标字符串。

指针实现的代码

#include <stdio.h>
#include <stdint.h>

void mystrcpy(void *dest, void *src)
{

    char *_dest = (char*)dest;
    char *_src = (char*)src;

    *_dest = *_src;
    printf("%c %c\n",*_src,*_dest);
    printf("%p %p\n",_src,_dest);
    _src++ ; _dest++;


    *_dest = *_src;
    printf("%c %c\n",*_src,*_dest);
    printf("%p %p\n",_src,_dest);
    _src++ ; _dest++;


    *_dest = *_src;
    printf("%c %c\n",*_src,*_dest);
    printf("%p %p\n",_src,_dest);
    _src++ ; _dest++;

    *_dest = '\0';

    printf("Final - %d %d %d  %p %p %p\n",_dest[0],_dest[1],_dest[2],&_dest[0],&_dest[1],&_dest[2]);
}

int main()
{
    char *src = "ABC";
    char dest[20];
    printf("%p %p\n",src,dest);
    mystrcpy(dest,src);

    return 0;
}

输出结果

0000000000404034 000000000061FE00

A A

0000000000404034 000000000061FE00

B B

0000000000404035 000000000061FE01

C C

0000000000404036 000000000061FE02

Final - 0 0 0 000000000061FE03 000000000061FE04 000000000061FE05

问题原因

核心错误是最终打印时使用的_dest指针已经经过多次递增,不再指向目标数组的起始位置:

  1. 初始时_dest指向dest数组的起始地址0x61FE00
  2. 每完成一次字符赋值后,_dest都会执行递增操作:
    • 第一次赋值后,_dest指向0x61FE01
    • 第二次赋值后,_dest指向0x61FE02
    • 第三次赋值后,_dest指向0x61FE03
  3. 最后给*_dest赋值'\0',此时_dest仍指向0x61FE03
  4. 打印_dest[0]、_dest[1]、_dest[2]时,实际访问的是0x61FE03、0x61FE04、0x61FE05这几个位置——而真正的A、B、C存储在0x61FE00、0x61FE01、0x61FE02,你访问的是未初始化的内存(或仅赋值了'\0'的位置),所以输出异常。

修正方案

只需要保存_dest的初始地址,最终打印时使用初始地址即可:

#include <stdio.h>
#include <stdint.h>

void mystrcpy(void *dest, void *src)
{

    char *_dest = (char*)dest;
    char *start_dest = _dest; // 保存初始地址
    char *_src = (char*)src;

    *_dest = *_src;
    printf("%c %c\n",*_src,*_dest);
    printf("%p %p\n",_src,_dest);
    _src++ ; _dest++;


    *_dest = *_src;
    printf("%c %c\n",*_src,*_dest);
    printf("%p %p\n",_src,_dest);
    _src++ ; _dest++;


    *_dest = *_src;
    printf("%c %c\n",*_src,*_dest);
    printf("%p %p\n",_src,_dest);
    _src++ ; _dest++;

    *_dest = '\0';

    // 使用初始地址打印正确的内容
    printf("Final - %c %c %c  %p %p %p\n",start_dest[0],start_dest[1],start_dest[2],&start_dest[0],&start_dest[1],&start_dest[2]);
    // 直接打印字符串
    printf("Final String - %s\n", start_dest);
}

int main()
{
    char *src = "ABC";
    char dest[20];
    printf("%p %p\n",src,dest);
    mystrcpy(dest,src);

    return 0;
}

修正后的输出会正确显示A、B、C以及对应的起始地址,并且可以正常打印字符串ABC。

内容的提问来源于stack exchange,提问作者Vishnu CS

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 14:41:00