发现问题了。 问题代码:
qint64 dataSize = 2701131776;
char* yuanshuju = new char[dataSize];
可行代码:
char* yuanshuju = new char[2701131776];
c++,牛 我反正是没搞懂
![]() |
1
yougg 2024-03-21 10:05:14 +08:00 ![]() 先把变量名改为 metadata 吧, 看到这里就难受无法继续阅读了......
|
![]() |
2
proxytoworld 2024-03-21 10:07:34 +08:00
同意一楼的
|
4
deplives 2024-03-21 10:13:17 +08:00
这个 yuanshuju 血压升高
|
5
Mithril 2024-03-21 10:14:33 +08:00 ![]() 用 memory mapping ,不要手动去读它。
|
6
silentx 2024-03-21 10:15:50 +08:00
是啥东西要一次性读到内存里处理?不考虑分段读吗?不是每个人的机器都是 32G 内存起步的啊。。。
|
![]() |
7
maokg 2024-03-21 10:16:45 +08:00
不知道一次性读 2.51GB 数据的应用场景是什么
|
![]() |
9
geelaw 2024-03-21 10:17:06 +08:00 ![]() 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 |
11
Crawping 2024-03-21 10:19:25 +08:00
理论 64 位程序的寻址空间是可以到 2'64 次字节
```C++ //你是真的这么写的 还是手写拷贝的? 中间为啥会有 ',' 逗号 char* yuanshuju = new char[2,701,131,776] ``` 学其他语言问 GPT 比发帖要来得快 |
![]() |
12
geelaw 2024-03-21 10:19:53 +08:00 ![]() @geelaw #9 没有超过 size_t (((φ(◎ロ◎;)φ))) 是 MSVC 只支持至多 2147483647 个元素。
|
![]() |
15
tool2d 2024-03-21 10:28:55 +08:00
我用 malloc ,别说是 malloc(2701131776)可以, 就算 malloc(4701131776)也行。
应该只是你内存不够的原因。”不够“不是说总剩余内存不够,而是无法分配一块巨大内存。 |
![]() |
16
shuax 2024-03-21 10:31:29 +08:00
改成 64 位轻轻松松。
|
17
greycell 2024-03-21 10:32:10 +08:00
笑死,元数据 2 个 g ,还在嘴硬。
|
![]() |
18
MoYi123 2024-03-21 10:33:48 +08:00 ![]() 建议发一下编译器的版本
或者试试看这样写 auto alloc = vector<int64_t>(2701131776 / 8 + 1); char* yuanshuju = reinterpret_cast<char*>(alloc.data()); |
19
clue 2024-03-21 10:34:32 +08:00
能流式处理不? 为什么一定要全读到内存里?
|
20
royking930911 2024-03-21 10:37:49 +08:00
从原数据着手吧 一次申请几个 G 的内存就算这次运行不出问题 下次也会崩
修改方法:1,分段读取 分段解析 2,优化算法 保存分段前后缓存数据和状态 |
21
yuzii 2024-03-21 10:38:56 +08:00
|
![]() |
22
yolee599 2024-03-21 10:47:30 +08:00
这么大一个数组,我看着都头疼,考虑分多次处理吧,每次大概分配 4096 字节
|
![]() |
23
shawnsh 2024-03-21 10:51:06 +08:00 via Android
大力出奇迹啊,先设计设计
|
![]() |
24
SmartTom OP 发现问题了。
问题代码: qint64 dataSize = 2701131776; char* yuanshuju = new char[dataSize]; 可行代码: char* yuanshuju = new char[2701131776]; c++,牛 我反正是没搞懂 |
![]() |
27
Geekerstar 2024-03-21 11:16:39 +08:00
我还以为是 yushengjun (余胜军)
|
![]() |
28
amorphobia 2024-03-21 12:08:42 +08:00
|
29
vsomeone 2024-03-21 12:19:22 +08:00 ![]() 根据你给的附言,推测可能是你 qtglobal 头文件引入的有问题,导致 qint64 被认为是 int32_t 。因为 2701131776 > INT_MAX(1 << 32 - 1),这个值在 assign 给 int32_t dataSize 之后被认为是一个负数,导致 bad_alloc 。
|
30
vsomeone 2024-03-21 12:20:19 +08:00
@amorphobia 他这个不是变长数组呀,用了 new 分配在堆上的,变长数组指的是分配在栈上的
|
![]() |
31
nagisaushio 2024-03-21 12:24:11 +08:00 via Android
这么大文件为什么不 mmap?
|
32
MrKrabs 2024-03-21 13:10:14 +08:00
2.51G 就大了?你们用的都是黄金内存吗
|
![]() |
33
amorphobia 2024-03-21 14:15:08 +08:00 via iPhone
@vsomeone 是我想错了
|
34
march1993 2024-03-21 14:24:00 +08:00
一个动态申请的,一个是放在静态区的?
|
![]() |
35
JustdoitSoso 2024-03-21 14:28:51 +08:00 via Android ![]() @vsomeone 感觉你说的是最有可能得情况,人家来请教问题,一群没分析没讨论的在说变量命名。
|
36
yuruizhe 2024-03-21 14:43:13 +08:00
试试用
constexpr qint64 dataSize = 2701131776; 行不行? |
37
NEO17 2024-03-21 15:04:52 +08:00
看了这段代码,不建议再写 C++ :)
|
![]() |
38
litguy 2024-03-21 15:28:35 +08:00
这个不是应该 mmap 的方式访问么 ?
|
![]() |
39
araraloren 2024-03-21 15:30:19 +08:00
Why you need load whole data to memory?
|
40
ltyj2003 2024-03-21 15:42:10 +08:00 via Android
动态长度用 vector
或者定义一个 char* ,然后 malloc 分配内存空间。 |
41
cnbatch 2024-03-21 15:44:33 +08:00
@amorphobia 这么大的 VLA ,存在爆栈的可能性吧(视乎编译器做法而定)
|
![]() |
42
amorphobia 2024-03-21 16:13:25 +08:00
|
43
cnbatch 2024-03-21 16:19:43 +08:00 ![]() 等等,为什么要用 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 ,就可以跳过这一步,它们都会自动初始化。 |
![]() |
44
yougotme 2024-03-21 21:39:04 +08:00 via iPhone
@SmartTom 立即数后面加上 LL ,明确指定长度。否则编译器可能会误判你是 int32 转 int64 ,可能变负数、可能溢出。
|
![]() |
45
yougotme 2024-03-21 21:40:25 +08:00 via iPhone
vs2022 肯定会抛一个警告出来的,也许你忽略了或者编译器不够新
|