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

多次调用memcpy出现输出异常 咨询动态长度数据处理方法

问题分析:memcpy动态长度数据处理异常

问题代码

// Powered by Judge0
#include <stdio.h>
#include <string.h>
#include <stdint.h>

typedef struct {
    char data[500];
    uint32_t len;
} payload;

void at_start(payload* payloadData)
{
    char p1[20] = "HI\r\n";
    memcpy(payloadData->data, p1, 4);
    payloadData->len = 4;
}

void at_net(payload* payloadData)
{
    char p1[20] = "HI CMDCMD\r\n";
    memcpy(payloadData->data, p1, 14);
    payloadData->len = 14;
}

int main(void) {
    payload* payloadData;
    at_start(payloadData);
    printf("Data : %s \n", payloadData->data);
    at_net(payloadData);
    printf("Data : %s \n", payloadData->data);
    at_start(payloadData);
    printf("Data : %s \n", payloadData->data);
    
    printf("Hello Judge0!\n");
    return 0;
}

运行输出

Data : HI
 
Data : HI CMDCMD
 
Data : HI
MDCMD

问题根源

  1. 指针未分配有效内存:main函数中payload* payloadData;仅声明了指针,未指向任何合法内存区域,直接通过该指针操作结构体属于未定义行为,可能引发内存越界、数据覆盖等随机错误。
  2. 缺少字符串结束符:memcpy仅复制指定长度的字节,但未在有效数据末尾添加'\0'。printf("%s")会从起始地址一直读取到'\0'才停止,当后续写入的数据长度短于之前的内容时,内存中残留的旧数据会被错误输出。比如最后一次调用at_start仅写入4字节,但之前at_net写入的14字节中,第4字节之后的内容仍留在内存中,就会被printf一并输出。

正确处理方案

1. 为结构体分配有效内存

有两种可靠方式:

  • 栈上分配:直接声明结构体变量,避免指针空悬问题,适合小内存结构体:
    payload payloadData; // 栈上分配完整结构体
    at_start(&payloadData); // 传入结构体地址
    
  • 堆上动态分配:适合大内存或需要长期持有的结构体,记得使用后释放:
    payload* payloadData = malloc(sizeof(payload));
    if (payloadData == NULL) {
        // 内存分配失败的异常处理
        return 1;
    }
    // 使用完成后释放内存
    free(payloadData);
    

2. 确保字符串以'\0'结尾

每次调用memcpy写入数据后,在有效长度的下一个位置添加字符串结束符,让printf能正确识别数据边界:

void at_start(payload* payloadData)
{
    char p1[20] = "HI\r\n";
    memcpy(payloadData->data, p1, 4);
    payloadData->len = 4;
    payloadData->data[payloadData->len] = '\0'; // 添加结束符
}

void at_net(payload* payloadData)
{
    char p1[20] = "HI CMDCMD\r\n";
    memcpy(payloadData->data, p1, 14);
    payloadData->len = 14;
    payloadData->data[payloadData->len] = '\0'; // 添加结束符
}

修改后的完整代码

// Powered by Judge0
#include <stdio.h>
#include <string.h>
#include <stdint.h>

typedef struct {
    char data[500];
    uint32_t len;
} payload;

void at_start(payload* payloadData)
{
    char p1[20] = "HI\r\n";
    memcpy(payloadData->data, p1, 4);
    payloadData->len = 4;
    payloadData->data[payloadData->len] = '\0';
}

void at_net(payload* payloadData)
{
    char p1[20] = "HI CMDCMD\r\n";
    memcpy(payloadData->data, p1, 14);
    payloadData->len = 14;
    payloadData->data[payloadData->len] = '\0';
}

int main(void) {
    payload payloadData;
    at_start(&payloadData);
    printf("Data : %s \n", payloadData.data);
    at_net(&payloadData);
    printf("Data : %s \n", payloadData.data);
    at_start(&payloadData);
    printf("Data : %s \n", payloadData.data);
    
    printf("Hello Judge0!\n");
    return 0;
}

修改后运行输出会正常显示每次的有效数据,不会出现残留内容。

内容的提问来源于stack exchange,提问作者Durga Suthar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 15:45:32