首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用指向C/C++中未对齐内存地址的指针访问结构是否安全?

使用指向C/C++中未对齐内存地址的指针访问结构是否安全?
EN

Stack Overflow用户
提问于 2021-12-30 11:34:30
回答 2查看 262关注 0票数 0
代码语言:javascript
复制
struct CustomData
{
    char flag;
    int count;
    double value;
};

CustomData custom_data{};

char *buf = new char[sizeof(CustomData) + 3];
memcpy(buf + 3, &custom_data, sizeof(CustomData));

CustomData* ptr = (CustomData *)(buf + 3);

ptr->count = 10;
ptr->value = 20.0;

我有一个由头字节和结构组成的内存缓冲区。对于这个内存缓冲区,结构是memcpy。我必须修改这个嵌入式结构中的一些字段,就像上面演示的那样。

我的问题是:

  1. ,这是x86-64的安全访问吗?其他平台怎么样?

  1. memcpy到本地结构,修改它并将其复制回来肯定是可以的,但它似乎是浪费的。是否有方法检查ptr是否正确地对齐以确保对结构的安全访问?
EN

回答 2

Stack Overflow用户

发布于 2021-12-30 11:45:07

C标准和C++标准都没有定义访问内存的行为,而不定义lvalue类型所需的对齐方式,甚至在指针值没有目标类型所需的对齐时,也没有定义将指针转换为另一个指针类型的行为。问题不在于您的目标体系结构(x86-64或其他)是否支持对齐访问,而是您的C或C++实现,特别是编译器是否支持它。

查看示例代码,我怀疑它是将数据从网络、文件或其他源复制到缓冲区的代理,然后尝试将该数据的一部分解释为所需的类型,可能是在检查接收数据中的头以确定主题数据的类型和/或位置之后。如果是这样的话,您应该描述原始情况,因为您显示的代理代码不够。

当将原始数据从网络或文件中读取为字节时,最好将数据直接读入所需的结构。理想情况下,将指定通信协议以根据需要对齐数据,以便在数据被接收到对齐缓冲区后不再需要进一步的操作。在C语言中,工会可以帮助处理将一种数据作为另一种数据混在一起的问题。

如果直接进入结构方法失败,memcpy可能会被使用,而且它可能不会像您想象的那样低效,因为memcpy方法会导致代码具有定义良好的行为,然后编译器通常可以在代码的相关部分有足够的可见性的情况下,优化它生成的程序集,这样就不会发生实际的memcpy

否则,一些编译器对C和C++标准有不同的扩展,这些扩展允许您定义结构类型而不需要对齐,并可以使用任意类型访问内存(支持将字符数组作为其他类型进行混叠)。

至少在C中,动态分配的内存可以使用字符类型填充数据,然后按照有关“有效类型”的规则作为另一种类型访问。但是,必须遵守某些关于别名的规则,这不会允许访问不正确对齐的数据(没有使用上述扩展)。

票数 1
EN

Stack Overflow用户

发布于 2021-12-30 12:29:09

任何指针双关都是危险的,因为它可能打破严格的混叠规则。

您需要使用memcpy。大多数优化编译器都非常了解memcpy,并且通常不会发出对memcpy的实际调用。

代码语言:javascript
复制
typedef struct CustomData
{
    char flag;
    int count;
    double value;
}CustomData;


CustomData *foo(int val, double d)
{
    char *buf = new char[sizeof(CustomData) + 3];

    CustomData cd;

    cd.count = val;
    cd.value = d;

    memcpy(buf + 3, &cd, sizeof(cd));
    return (CustomData *)buf;
}
代码语言:javascript
复制
foo(int, double):
        push    rbp
        mov     ebp, edi
        mov     edi, 19
        push    rbx
        sal     rbp, 32
        movq    rbx, xmm0
        sub     rsp, 8
        call    operator new[](unsigned long)
        mov     QWORD PTR [rax+3], rbp
        mov     QWORD PTR [rax+11], rbx
        add     rsp, 8
        pop     rbx
        pop     rbp
        ret
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70531062

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档