奇怪的malloc行为在64位进程上无法允许超过2GB的内存分配

3
这个问题涉及到我正在开发的一个程序。
我正在开发一个需要在网络上传输的行集或单行大于2GB的项目(网络无法发送大于2GB的数据组)。我已经对代码进行了适当的更改,以便不会发送这些组/行,但现在我正在尝试构建测试用例。
我已经构建了一个测试,创建了少于10亿行,占用超过2GB。程序在将这些行组发送到网络之前正确地过滤掉它们。
我的问题是,我需要创建一个单行,其中包含一个包含单个字符串或多列包含字符串的集合的列,该行的大小大于2GB。但是,当字符串开始接近2GB时,malloc返回NULL。
我进行了一些研究,并发现这可能是因为我没有足够的连续内存,因此我开始添加更多列和较小的字符串。我甚至分成64列,以便不必立即分配那么多空间。然而,我仍然遇到同样的问题,我怀疑自己可能忽略了什么。
这是64位Windows 7系统上的64个进程,拥有8GB的RAM。(但我还在一台64位红帽机器上测试了它,有24GB的RAM)
有人知道为什么系统在接近2GB时无法分配程序内存吗?
附言:我也研究了64位系统上每个进程可以分配的内存,超过100TB。鉴于如此之多,我无法在接近2GB时进行分配真正让我困惑。

2
你是否使用了足够大的整数类型来存储大小?我假设你正在运行64位操作系统,而不仅仅是64位硬件? - Thomas Padron-McCarthy
1
@TopGunCoder:gcAllowVeryLargeObjects是针对.NET框架的。这是一个C++应用程序,对吧?我有相同的配置,并且使用10GB运行良好(尽管分配需要一些时间)。 - Jesse Good
2
那么,编写一个最小的、可编译的程序来展示这种行为怎么样?花时间去写它。如果该程序没有显示错误,则问题可能出现在代码的其他地方。如果有错误,那么找出问题将会更容易。 - Thomas Padron-McCarthy
1
@TopGunCoder:不,不要重新创建实现!只需编写一个非常小的程序,尝试以类似于您的真实程序的方式分配内存。如果这样可以工作,那么您的问题可能不在于内存分配,您可以停止查看配置等内容。 - Thomas Padron-McCarthy
1
我找到问题所在了!就在我准备继续之前,我注意到有人在之前的更改中将变量类型从32位无符号更改为有符号。因此,当我的巨大行溢出并传递到我拥有的分配包装器时,负位将转移到64位无符号数的负位...创建了一个巨大的内存量,它试图分配!谢谢大家的帮助!!如果不是你们提出如此彻底的建议,我不会注意到这种微妙的差别:D:D:D: - CoderDake
显示剩余17条评论
1个回答

2
经过对代码组的深入探索,我发现传递给的大小是由一个返回有符号整数的函数计算的。由于这个数字被溢出,当它被编译器转换为时,最高位被设置了。这当然导致calloc试图分配大量内存。
当然,有几种可能的解决方案:
1. 将大小函数的返回类型更改为(这对我的代码库和时间限制来说都太大了); 2. 在将其传递给calloc之前将大小函数的结果转换为(我选择的选项,暂时绕过了大型分配)。
希望这能帮助其他人,

为什么不返回 size_t 作为大小的类型? - phuclv

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接