RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 763633
Accepted
Mikhailo
Mikhailo
Asked:2020-12-27 01:14:30 +0000 UTC2020-12-27 01:14:30 +0000 UTC 2020-12-27 01:14:30 +0000 UTC

为任意类型的数组分配无类型内存

  • 772

如果我为某种类型分配内存T- 让它在模板中,让我们说 -

template<typename T>
char* alloc(size_t n) { return new char[n*sizeof(T)] ; }

那么是否有足够的空间来存放n具有类型的元素T?有对齐问题吗?如果他们可以 - 如何正确解决它们?

另外-根据@VladD的建议,我尝试分配具有特殊对齐要求的内存:

#include <iostream>
#include <typeinfo>

using namespace std;

struct alignas(256) D {
    char a;
    char b;
    };

template<typename T>
void* alloc(size_t n) {
    return reinterpret_cast<void*>(new
                                   aligned_storage<sizeof(T), alignof(T)>[n]);
    }

template<typename T>
int allocSize() {
    cout << "sizeof = " << sizeof(T) << ", alignof = " << alignof(
             T) << endl;
    cout << "type = " << typeid(typename
                                aligned_storage<sizeof(T), alignof(T)>::type).name() << endl;
    return sizeof(typename
                  aligned_storage<sizeof(T), alignof(T)>::type);
    }


int main() {
    cout << allocSize<D>() << endl;
    cout << alloc<D>(5) << endl;
    }

GCC 无法解决 - https://ideone.com/dgo75h。但 Visual Studio 工作正常,但发出:

sizeof = 256, alignof = 256
type = union std::_Align_type<double,256>
256
004A1258

那些。我理解大小和对齐方式,但地址显然没有对齐到 256。我不需要这种对齐方式,这是真的,游戏 - 但事实证明,这样分配内存是不可能的?

c++
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. AnT stands with Russia
    2020-12-27T01:50:24Z2020-12-27T01:50:24Z

    不,不会有任何问题。

    首先,保证有足够的空间。

    其次,关于对齐,new-expression 确保分配的new char[n]内存与最强的基本对齐要求对齐。也就是说,内存将对齐到alignof(std::max_align_t). 从 new-expression 派生的内存将正确对齐以存储任何支持实现的基本类型和由它们构造的类型。

    3.7.4.1 分配函数
    2 [...] 返回的指针应适当对齐,以便可以将其转换为指向任何合适的完整对象类型(18.6.2.1)的指针,然后用于访问对象或数组分配的存储空间(直到通过调用相应的释放函数显式释放存储空间)。[...]

    5.3.4 New
    11当一个new-expression调用一个分配函数并且该分配没有被扩展时,new-expression将请求的空间量作为 type 的第一个参数传递给分配函数std::size_t。该参数不应小于正在创建的对象的大小;只有当对象是一个数组时,它才可能大于正在创建的对象的大小。对于 和 的数组,char新表达式unsigned char的结果之间的差异并且分配函数返回的地址应该是任何对象类型的最严格的基本对齐要求(3.11)的整数倍,其大小不大于正在创建的数组的大小。[注意:因为分配函数被假定返回指向存储的指针,该指针对于具有基本对齐的任何类型的对象都进行了适当对齐,因此对数组分配开销的这种约束允许分配字符数组的常见习惯用法,稍后将在其中放置其他类型的对象. ——尾注]

    上面的引用以纯文本的形式表示,精确地引入了对分配的内存块结构的限制,new char[n]以确保在使用特定的内存分配方式时正确对齐。

    因此,除非您有一些超出最大基本对齐的特殊高级对齐要求,否则您无需担心对齐。

    • 7
  2. Best Answer
    VladD
    2020-12-27T01:35:56Z2020-12-27T01:35:56Z

    理论上,您需要std::aligned_storage.

    它应该像这样工作:

    template<typename T>
    char* alloc(size_t n)
    {
        return new aligned_storage<sizeof(T), alignof(T)>[n];
    }
    

    简单方法对齐的问题很明显:new char[]它不知道您的对齐要求,并且可能分配未对齐的内存。


    要在内存中分配对象,您需要放置新的。你应该派上用场std::align了,这里描述了它的使用。


    更新:我仔细检查过,它实际上并没有new遵守自定义对齐要求。因此,您需要自己进行对齐,使用std::align. 事实证明:

    // подсчёт длины нужной аллокации
    template<typename T>
    size_t aligned_char_size(size_t n)
    {
        size_t result = n * sizeof(T);
        bool is_overaligned = alignof(T) > alignof(std::max_align_t);
        if (is_overaligned)
            result += alignof(T) - 1;
        return result;
    }
    

    我们申请:

    struct alignas(1024) S
    {
    };
    
    // выделёем память на 3 экземпляра
    size_t total_space = aligned_char_size<S>(3);
    void* p = new char[total_space];
    std::cout << p << std::endl;
    
    // получаем выровненный указатель при помощи std::align
    void* allocated_item = p;
    size_t remaining_space = aligned_char_size<S>(3);
    if (std::align(alignof(S), sizeof(S), allocated_item, remaining_space))
    {
        std::cout << allocated_item << std::endl;
        std::cout << (size_t)allocated_item % alignof(S) << std::endl;
    }
    else
    {
        std::cout << "Impossible" << std::endl;
    }
    

    Visual Studio 2017 上的结果:

    000002333DF15950
    000002333DF15C00
    0
    

    如果我们删除alignas(1024),我们得到

    000002A27FD2ECD0
    000002A27FD2ECD0
    0
    
    • 3

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    Python 3.6 - 安装 MySQL (Windows)

    • 1 个回答
  • Marko Smith

    C++ 编写程序“计算单个岛屿”。填充一个二维数组 12x12 0 和 1

    • 2 个回答
  • Marko Smith

    返回指针的函数

    • 1 个回答
  • Marko Smith

    我使用 django 管理面板添加图像,但它没有显示

    • 1 个回答
  • Marko Smith

    这些条目是什么意思,它们的完整等效项是什么样的

    • 2 个回答
  • Marko Smith

    浏览器仍然缓存文件数据

    • 1 个回答
  • Marko Smith

    在 Excel VBA 中激活工作表的问题

    • 3 个回答
  • Marko Smith

    为什么内置类型中包含复数而小数不包含?

    • 2 个回答
  • Marko Smith

    获得唯一途径

    • 3 个回答
  • Marko Smith

    告诉我一个像幻灯片一样创建滚动的库

    • 1 个回答
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Алексей Шиманский 如何以及通过什么方式来查找 Javascript 代码中的错误? 2020-08-03 00:21:37 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5