【C/C++】malloc 最大能申请的一维数组空间是4G?

本文介绍了一种在读取大量二进制文件时遇到的大内存分配问题及其解决方案。通过使用int64_t类型而非int32_t类型进行内存大小计算,成功避免了因整数溢出导致的内存分配失败。

问题描述

现在有128个二进制文件要读取到内存,每个文件大小都是269.4MB。每个文件有2^15条数据,每条数据大小为2*N*sizeof(uint32_t) = 2*1024*4 = 8192字节。我的想法是,定义一个一维指针数组database,所有文件的数据都存到database

@Override
 //每个文件有2^15条数据,每条数据大小为2*N*sizeof(uint32_t)=2*1024*4=8192字节
	int flen = 1 << 15;
	uint32_t *database=(uint32_t*)malloc(128 * flen * 2 * N * sizeof(uint32_t));
	//循环调用读取文件的函数,该函数每次只读取一个文件
	for(int i = 0; i < 128; i++){
		ReadDatabase(flen, database + i * flen * 2 * N);
	}

因为我当时是采用MPI多进程跑的程序,4台机器都要在各自的磁盘上读取128个二进制文件(这些文件是不同的),结果编译的时候没出现问题,运行的时候会报出:

BAD TERMINATION OF ONE OF YOUR APPLICATION PROCESSES EXIT CODE: 139

当时经过我的测试,给database分配16个二进制文件的空间,即:
16∗flen∗2∗N∗sizeof(uint32_t)=16∗215∗2∗1024∗4=4G16*flen*2*N*sizeof(uint32\_t)=16*2^{15}*2*1024*4=4G16flen2Nsizeof(uint32_t)=16215210244=4G
程序就能正常运行,所以我就以为malloc一次最多能分配的空间为4G。

原因分析:

后面经过大佬的帮忙,我才知道我在分配database空间的时候,没有把真正想要分配的空间的大小分配到database,我当时很疑惑就做了测试,输出malloc的size大小,果然震惊到我了,输出来的是负数!!

原来malloc(128 * flen * 2 * N * sizeof(uint32_t))的时候,里面的表达式结果超出了默认的int32_t所能表示的范围,因此要改成int64_t


解决方案:

@Override
 //每个文件有2^15条数据,每条数据大小为2*N*sizeof(uint32_t)=2*1024*4=8192字节
	int flen = 1 << 15;
	int64_t arr_size = 2 * N * sizeof(uint32_t);
	arr_size *= 128 * flen;
	uint32_t *database=(uint32_t*)malloc(arr_size);
	//循环调用读取文件的函数,该函数每次只读取一个文件
	for(int64_t i = 0; i < 128; i++){
		ReadDatabase(flen, database + i * flen * 2 * N);
	}

注意循环读取文件的时候,循环变量i也要改成int64_t,否则访问不到想要的内存

### 使用C++中的malloc函数动态开辟一维数组C++中,`malloc` 是一个从C语言继承而来的函数,用于在运行时动态分配内存。通过 `malloc` 可以为一维数组分配内存空间,并且需要确保在使用完后释放该内存,以避免内存泄漏。 以下是具体实现方式: #### 动态分配代码示例 ```cpp #include <iostream> #include <cstdlib> // 包含 malloc 和 free 的头文件 int main() { int size; std::cout << "请输入数组小: "; std::cin >> size; // 使用 malloc 分配内存 int* arr = (int*)malloc(size * sizeof(int)); if (arr == nullptr) { // 检查内存分配是否成功 std::cerr << "内存分配失败!" << std::endl; return 1; } // 初始化数组并打印 for (int i = 0; i < size; ++i) { arr[i] = i + 1; // 假设填充为从1开始的整数序列 std::cout << "arr[" << i << "] = " << arr[i] << std::endl; } // 释放内存 free(arr); arr = nullptr; // 防止悬空指针 return 0; } ``` #### 关键点解析 - **分配内存**:`malloc` 函数返回的是 `void*` 类型的指针,因此需要强制类型转换为目标类型的指针。例如,在上述代码中 `(int*)malloc(size * sizeof(int))` 表示为 `int` 类型的一维数组分配内存[^2]。 - **检查分配结果**:如果 `malloc` 返回 `nullptr`,则表示内存分配失败。此时应采取适当的错误处理措施。 - **释放内存**:使用 `free` 函数释放由 `malloc` 分配的内存。释放后将指针置为 `nullptr`,可以防止出现悬空指针问题[^2]。 #### 注意事项 - 在C++中,更推荐使用 `new` 和 `delete[]` 来动态分配和释放内存,因为它们与C++的对象模型更加兼容。然而,`malloc` 和 `free` 也可以在C++中使用,但需要注意它们不会调用构造函数或析构函数[^5]。 - 动态分配的内存必须显式释放,否则会导致内存泄漏。尤其是在循环或递归中频繁分配内存时,这一点尤为重要。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值