关于 C++读取大小为 2.51 GB (2,701,131,776 字节)到 char* yuanshuju 数组中去 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
SmartTom
0.12D
V2EX    程序员

关于 C++读取大小为 2.51 GB (2,701,131,776 字节)到 char* yuanshuju 数组中去

  •  
  •   SmartTom 2024-03-21 09:58:00 +08:00 3613 次点击
    这是一个创建于 619 天前的主题,其中的信息可能已经有所发展或是发生改变。
    如题,现在想实现将这个大文件(大小超过 int 最大范围)的文件放入到 char* yuanshuju = new char[2,701,131,776]中
    现在就卡在第一步定义 yuanshuju 这一步,qt 一直提示"terminate called after throwing an instance of 'std::bad_alloc'
    what(): std::bad_alloc",本人没太做过 c++,这个提示是代表不能定义那么大的数组吗?还有别的可行方案吗。
    系统:win11 64 位
    QT: 5.12.12
    第 1 条附言    2024-03-21 10:53:35 +08:00

    发现问题了。 问题代码:

    qint64 dataSize = 2701131776; char* yuanshuju = new char[dataSize]; 

    可行代码:

    char* yuanshuju = new char[2701131776]; 

    c++,牛 我反正是没搞懂

    45 条回复    2024-03-21 21:40:25 +08:00
    yougg
        1
    yougg  
       2024-03-21 10:05:14 +08:00   3
    先把变量名改为 metadata 吧, 看到这里就难受无法继续阅读了......
    proxytoworld
        2
    proxytoworld  
       2024-03-21 10:07:34 +08:00
    同意一楼的
    iOCZS
        3
    iOCZS  
       2024-03-21 10:12:28 +08:00   2
    是 rawdata ,不是 metadata
    @yougg
    deplives
        4
    deplives  
       2024-03-21 10:13:17 +08:00
    这个 yuanshuju 血压升高
    Mithril
        5
    Mithril  
       2024-03-21 10:14:33 +08:00   4
    用 memory mapping ,不要手动去读它。
    silentx
        6
    silentx  
       2024-03-21 10:15:50 +08:00
    是啥东西要一次性读到内存里处理?不考虑分段读吗?不是每个人的机器都是 32G 内存起步的啊。。。
    Yasuke
        7
    Yasuke  
       2024-03-21 10:16:45 +08:00
    不知道一次性读 2.51GB 数据的应用场景是什么
    SmartTom
        8
    SmartTom  
    OP
       2024-03-21 10:16:59 +08:00
    @deplives 哈哈 我也是接手别人的项目,这不是我的风格。
    geelaw
        9
    geelaw  
       2024-03-21 10:17:06 +08:00   2
    new char[2,701,131,776] 会分配长度是 776 个元素的 char 数组,不是你期待的 2.51 GB 。

    int main() { new char[2701131776] { }; }

    这个程序在我的电脑上编译为 64 位的话可以正常运行,并且确实占用了 2.51 GB 内存,如果用 32 位编译器则编译失败,因为分配的数组规模超过了 size_t 。

    抛出 std::bad_alloc 的意思就是分配失败,或许你的页面文件和实体内存不够大。

    如果数据来自于文件,可以用内存映射文件,Windows 的文档是 https://learn.microsoft.com/en-us/windows/win32/memory/file-mapping
    POSIX 的文档是 https://pubs.opengroup.org/onlinepubs/9699919799/functions/mmap.html
    SmartTom
        10
    SmartTom  
    OP
       2024-03-21 10:17:29 +08:00
    @maokg 光谱数据处理,体谅挺大的
    Crawping
        11
    Crawping  
       2024-03-21 10:19:25 +08:00
    理论 64 位程序的寻址空间是可以到 2'64 次字节
    ```C++
    //你是真的这么写的 还是手写拷贝的? 中间为啥会有 ',' 逗号
    char* yuanshuju = new char[2,701,131,776]
    ```
    学其他语言问 GPT 比发帖要来得快
    geelaw
        12
    geelaw  
       2024-03-21 10:19:53 +08:00   1
    @geelaw #9 没有超过 size_t (((φ(◎ロ◎;)φ))) 是 MSVC 只支持至多 2147483647 个元素。
    SmartTom
        13
    SmartTom  
    OP
       2024-03-21 10:20:14 +08:00
    @Crawping 这个我的问题,我是手动在编辑标题的时候赋值计算器里面的值,实际是去掉','的
    yougg
        14
    yougg  
       2024-03-21 10:23:18 +08:00
    @iOCZS #3 "元数据"不是"原始数据"
    tool2d
        15
    tool2d  
       2024-03-21 10:28:55 +08:00
    我用 malloc ,别说是 malloc(2701131776)可以, 就算 malloc(4701131776)也行。

    应该只是你内存不够的原因。”不够“不是说总剩余内存不够,而是无法分配一块巨大内存。
    momo1999
        16
    momo1999  
       2024-03-21 10:31:29 +08:00
    改成 64 位轻轻松松。
    greycell
        17
    greycell  
       2024-03-21 10:32:10 +08:00 div class="sep5">
    笑死,元数据 2 个 g ,还在嘴硬。
    MoYi123
        18
    MoYi123  
       2024-03-21 10:33:48 +08:00   1
    建议发一下编译器的版本

    或者试试看这样写
    auto alloc = vector<int64_t>(2701131776 / 8 + 1);
    char* yuanshuju = reinterpret_cast<char*>(alloc.data());
    clue
        19
    clue  
       2024-03-21 10:34:32 +08:00
    能流式处理不? 为什么一定要全读到内存里?
    roykingH
        20
    roykingH  
       2024-03-21 10:37:49 +08:00
    从原数据着手吧 一次申请几个 G 的内存就算这次运行不出问题 下次也会崩
    修改方法:1,分段读取 分段解析
    2,优化算法 保存分段前后缓存数据和状态
    yuzii
        21
    yuzii  
       2024-03-21 10:38:56 +08:00
    yolee599
        22
    yolee599  
       2024-03-21 10:47:30 +08:00
    这么大一个数组,我看着都头疼,考虑分多次处理吧,每次大概分配 4096 字节
    shawnsh
        23
    shawnsh  
       2024-03-21 10:51:06 +08:00 via Android
    大力出奇迹啊,先设计设计
    SmartTom
        24
    SmartTom  
    OP
       2024-03-21 10:51:58 +08:00
    发现问题了。
    问题代码:
    qint64 dataSize = 2701131776;
    char* yuanshuju = new char[dataSize];
    可行代码:
    char* yuanshuju = new char[2701131776];

    c++,牛 我反正是没搞懂
    SmartTom
        25
    SmartTom  
    OP
       2024-03-21 10:54:56 +08:00
    @yolee599 是头疼,等一次采集任务结束,还要处理 50GB 的数据,哎~
    iold
        26
    iold  
       2024-03-21 10:58:34 +08:00   2
    @SmartTom #24 试试使用文档中提供的宏呢?
    Geekerstar
        27
    Geekerstar  
       2024-03-21 11:16:39 +08:00
    我还以为是 yushengjun (余胜军)
    amorphobia
        28
    amorphobia  
       2024-03-21 12:08:42 +08:00
    @SmartTom

    C++ 标准不支持“柔性数组/变长数组”,数组大小是变量的情况,应该用 vector

    一定要使用变量作数组长度的话,换 C 语言 (C99) 吧
    vsomeone
        29
    vsomeone  
       2024-03-21 12:19:22 +08:00   1
    根据你给的附言,推测可能是你 qtglobal 头文件引入的有问题,导致 qint64 被认为是 int32_t 。因为 2701131776 > INT_MAX(1 << 32 - 1),这个值在 assign 给 int32_t dataSize 之后被认为是一个负数,导致 bad_alloc 。
    vsomeone
        30
    vsomeone  
       2024-03-21 12:20:19 +08:00
    @amorphobia 他这个不是变长数组呀,用了 new 分配在堆上的,变长数组指的是分配在栈上的
    nagisaushio
        31
    nagisaushio  
       2024-03-21 12:24:11 +08:00 via Android
    这么大文件为什么不 mmap?
    MrKrabs
        32
    MrKrabs  
       2024-03-21 13:10:14 +08:00
    2.51G 就大了?你们用的都是黄金内存吗
    amorphobia
        33
    amorphobia  
       2024-03-21 14:15:08 +08:00 via iPhone
    @vsomeone 是我想错了
    march1993
        34
    march1993  
       2024-03-21 14:24:00 +08:00
    一个动态申请的,一个是放在静态区的?
    JustdoitSoso
        35
    JustdoitSoso  
       2024-03-21 14:28:51 +08:00 via Android   1
    @vsomeone 感觉你说的是最有可能得情况,人家来请教问题,一群没分析没讨论的在说变量命名。
    yuruizhe
        36
    yuruizhe  
       2024-03-21 14:43:13 +08:00
    试试用
    constexpr qint64 dataSize = 2701131776;
    行不行?
    NEO17
        37
    NEO17  
       2024-03-21 15:04:52 +08:00
    看了这段代码,不建议再写 C++ :)
    litguy
        38
    litguy  
       2024-03-21 15:28:35 +08:00
    这个不是应该 mmap 的方式访问么 ?
    araraloren
        39
    araraloren  
       2024-03-21 15:30:19 +08:00
    Why you need load whole data to memory?
    ltyj2003
        40
    ltyj2003  
       2024-03-21 15:42:10 +08:00 via Android
    动态长度用 vector
    或者定义一个 char* ,然后 malloc 分配内存空间。
    cnbatch
        41
    cnbatch  
       2024-03-21 15:44:33 +08:00
    @amorphobia 这么大的 VLA ,存在爆栈的可能性吧(视乎编译器做法而定)
    amorphobia
        42
    amorphobia  
       2024-03-21 16:13:25 +08:00
    @cnbatch

    是我想错了,这里不是 VLA

    如果真有这么大的 VLA ,我也高度怀疑会爆
    cnbatch
        43
    cnbatch  
       2024-03-21 16:19:43 +08:00   2
    等等,为什么要用 new 直接创建呢?最后还得手动 delete 。
    不如用 std::vector 或者 std::make_unique<char[]>(数据长度)
    这两个好多了

    std::vector 已经有人发了,那么 make_unique 的用法是:

    size_t data_size{2701131776};
    std::unique_ptr<char[]> raw_data_ptr = std::make_unique<char[]>(data_size);
    char* raw_data = raw_data_ptr.get();

    在我的 Windows 11 + VS2022 测了下,很成功,没任何报错。

    另外呢,直接用 malloc 、new 创建的空间,按照 C 语言留下来的“惯例”,是需要手动初始化的。
    通常会用 memset 初始化为零,用 std::fill 也可以。

    如果改用 std::vector 或者 std::make_unique ,就可以跳过这一步,它们都会自动初始化。
    yougotme
        44
    yougotme  
       2024-03-21 21:39:04 +08:00 via iPhone
    @SmartTom 立即数后面加上 LL ,明确指定长度。否则编译器可能会误判你是 int32 转 int64 ,可能变负数、可能溢出。
    yougotme
        45
    yougotme  
       2024-03-21 21:40:25 +08:00 via iPhone
    vs2022 肯定会抛一个警告出来的,也许你忽略了或者编译器不够新
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1064 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 33ms UTC 23:38 PVG 07:38 LAX 15:38 JFK 18:38
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86