我可以使用 std::align 来验证给定指针的对齐方式吗?

问题描述 投票:0回答:1

以下函数模板尝试在字节数组中定位对象。 我们可以假设参数

buffer
“通常”持有给定类型的对象,但我需要针对可能的错误进行诊断(断言检查)。

template <typename T>
T* get_object_from_buffer(std::uint8_t* buffer, std::size_t size)
{
    // EDIT: This constraint was missing in original version of the question.
    if (size != sizeof(T))
    {
        // Invalid usage of the function.
        return nullptr;
    }
    
    void* tmp_buffer = buffer;
    if (nullptr != std::align( alignof(T),
                               sizeof(T),
                               tmp_buffer,
                               size ) )
    {
        return reinterpret_cast<T*>(buffer);
    }
    else
    {
        // Caller can check returned pointer to implement diagnostic reactions
        return nullptr;
    }
}

问题:

  1. 是否允许(并且便携)使用

    std::align
    来执行此操作?

  2. 您是否看到更好的解决方案 - 更健壮、更优雅?

条件:

  • 该功能将在嵌入式系统上使用。 因此,一些关于 PC 平台上 std::align 使用的 google 搜索结果不适用。

  • 缓冲区由如下函数填充:

        template <typename T>
        std::pair<std::uint8_t*, std::size_t> put_object_into_buffer(T* object)
        {
            return std::pair<std::uint8_t*, std::size_t>(
                            reinterpret_cast<std::uint8_t*>(object),
                            sizeof(object)
                        );
        }
    

    在 put/get 函数之间,我必须通过一个不是的库传递缓冲区 了解用户定义的类型,例如

    T


编辑/更新

uint8_t*
size_t
的缓冲区表示仅用于保存单个
T
对象。原始问题帖子中缺少此内容。 我添加了检查,确保
size
参数实际上与对象的大小匹配。

如果没有此检查,

std::align()
可以轻松地在
T*
中找到对齐的
buffer
,因此该标准不再相关。 感谢 Ted Lyngmo 指出了这一点!

c++ c++14 memory-alignment
1个回答
0
投票

答案受到@Ted Lyngmo 的评论启发 - 请参阅问题评论

  • 针对

    size == sizeof(T)
    的检查至关重要。

    否则

    std::align()
    不会回来
    nullptr
    每当
    size
    超出未对齐的
    buffer
    指针时 允许放置整个、对齐的
    T
    实例 介于
    &(buffer[0])
    &(buffer[size-1])
    之间。

  • 在错误情况下使用

    nullptr
    函数返回值, 没有必要区分
    buffer
    tmp_buffer
    如果返回值是
    std::align()
    的类型转换。

    那么,函数可以缩短:

    template <typename T>
    T* get_object_from_buffer(std::uint8_t* buffer, std::size_t size)
    {
        if (size != sizeof(T))
        {
            // Invalid usage of the function.
            // Caller shall check returned pointer to implement diagnostic reactions
            return nullptr;
        }
        else
        {
            void* tmp_buffer = buffer;
            return reinterpret_cast<T*>(std::align(alignof(T), sizeof(T), tmp_buffer, size));
        }
    }
    

    甚至

     template <typename T>
     T* get_object_from_buffer(std::uint8_t* buffer, std::size_t size)
     {
         // Caller shall check returned pointer against 'nullptr' to implement diagnostic reactions
         return reinterpret_cast<T*>(
                 size == sizeof(T) 
                     ? std::align(alignof(T), sizeof(T), buffer, size) 
                     : nullptr);
     }
    
© www.soinside.com 2019 - 2024. All rights reserved.