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

为何使用memcpy操作结构体柔性数组后dst指针ndata值异常?

问题分析与解决:柔性数组拷贝后指针变量值异常的原因

核心原因

  • 柔性数组的本质:struct Block中的u_int8_t data[0]是C风格柔性数组占位符,本身不占用结构体内存。Block的大小仅为sizeof(int32_t)(4字节),ptr->data的地址是&block + sizeof(int32_t),即block实例之后的栈内存地址——这块内存不属于block,属于栈上其他区域(可能是局部变量、栈帧数据)。
  • 栈布局重叠导致变量被篡改:局部指针变量ndata的存储地址恰好和ptr->data指向的地址重叠。执行memcpy((void*)ndata, &data_buffer, sizeof(void*))时,实际是把&data_buffer的指针值写入到ndata变量自身的内存中,导致ndata值被修改为异常数值。
  • ptr->data地址不变的逻辑:ptr->data不是可修改变量,而是编译时确定的地址偏移表达式,永远等于&block + sizeof(int32_t)。只要block的地址不变,这个值就不会改变,和写入的内存内容无关。

代码中的错误点

  1. 错误认为ptr->data指向block的可用内存,直接写入属于栈越界访问,触发未定义行为。
  2. memcpy参数逻辑错误:目标是拷贝data_buffer内容,但代码中传递的是&data_buffer(数组的指针)而非data_buffer(数组起始地址)。

修正方案

正确使用柔性数组需要为结构体分配包含柔性数组的内存,通常用动态分配:

#include <cstring>
#include <cstdio>
#include <cstdlib>

struct Block {
    int32_t size;
    u_int8_t data[0];
};

int main(int argc, char **argv) {
    u_int8_t data_buffer[] = {1, 3, 0, 1, 3, 4, 5, 5, 6, 2, 2, 3};
    int data_size = sizeof(data_buffer);

    // 分配结构体+柔性数组的总内存
    Block *ptr = static_cast<Block*>(malloc(sizeof(Block) + data_size));
    if (!ptr) {
        perror("malloc failed");
        return 1;
    }
    ptr->size = data_size;

    // 拷贝数据到柔性数组区域
    memcpy(ptr->data, data_buffer, data_size);

    printf("data ptr: %p\n", ptr->data);
    for(int i = 0; i < ptr->size; i++) {
        printf("%d ", ptr->data[i]);
    }
    printf("\n");

    free(ptr);
    return 0;
}

额外说明

  • 若需在栈上使用类似结构,可考虑C99变长数组(VLA),但栈空间有限,不推荐在C++中使用。
  • 标准C++中更推荐用std::vector<uint8_t>替代柔性数组,避免手动内存管理风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 13:14:57