C二进制达到1.2G内存限制

标签 c memory memory-management 64-bit out-of-memory

我正在处理一个 C 程序,它从一个文件中读入许多 每行约 60 个字符,并在内存中分配字符串 通过在读取文件时请求更多内存。在每个 malloc 之后 请求,它会检查函数 OOM() 是否请求更多 内存成功。

我已经用越来越大的输入文件测试了程序,并且 OOM() 或多或少报告一个“Out of memory” 当内存 程序运行时查看top命令时使用量达到1.2G 在跑。这是在具有更多内存的 64 位 Linux 机器上 可用的。 文件/my/binary/program 的输出:

ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped

我的问题是:为什么会达到1.2G的限制?我记得我的 系统管理员过去常说某些二进制文件只能使用 高达 1.2G,巧合的是我在这里看到的。

当我在同一个 64 位 Linux 的节点上运行 qsub 相同的执行 SGE 网格保留 50GB 的内存,它报告说 "Out of memory” 和以下 SGE 日志内存占用:

Max vmem         = 2.313G

程序达到此内存限制的任何想法?有没有 我应该知道哪些编译标志可能会导致/解决这个问题?

在当前 Makefile 中找到下面的相关标志:

CC = gcc
CFLAGS = -Wall -O3 -funroll-loops -DNDEBUG -fomit-frame-pointer -std=gnu99 -msse2 -Wno-unused-function -Wno-unused-result
CFLAGSSFMT = -msse2 -DHAVE_SSE2 -O9 -finline-functions -fomit-frame-pointer \
-DNDEBUG -fno-strict-aliasing --param max-inline-insns-single=1800 -std=c99
LD = ld
LDFLAGS =  -lm -lc -lblas -llapack
INCFLAGS = 
DEFINES = -D_GNU_SOURCE -DUSE_BLAS

部分相关代码如下:w

mystring.h中:

#ifndef _MYSTRING_H_
#define _MYSTRING_H_

struct __mystring_struct {
   char * string;
   int len, maxlen;
};
typedef struct __mystring_struct * Mystring;
#define Mystring_size sizeof(struct __mystring_struct)

Mystring new_mystring (const int len);
void free_mystring (Mystring string);
void append_char_to_mystring ( const char c, Mystring string);
char * cstring_of_mystring(const Mystring string);
Mystring mystring_of_cstring (const char * str);
#endif

mystring.c中:

#include <string.h>
#include "mystring.h"

#define OOM(A) { if (NULL==(A) ){fputs("Out of memory\n",stderr); exit(EXIT_FAILURE);} }
static void check_is_mystring (const Mystring string);
static void double_length_of_mystring ( Mystring string);

稍后:

static void double_length_of_mystring (Mystring string){
   char * new_mem;
   check_is_mystring(string);

   new_mem = malloc(string->maxlen * 2 * sizeof(char)); OOM(new_mem);
   memcpy (new_mem,string->string,string->len * sizeof(char));
   free(string->string);
   string->string = new_mem;
   string->maxlen *= 2;

   check_is_mystring (string);
}

最佳答案

您似乎使用 int 来保持字符串的大小。在 GCC(以及大多数其他 PC 平台编译器)中,此类型 is 32b even on 64b platform .您应该改用 size_t

分配失败的机制如下:

  • 1.2GB ~= 1288490189
  • 2 * 1.2 GB ~= 2576980378,超过 2^31 (2147483648),溢出后在二次补码运算中得到 -1717986918
  • 当调用 malloc 时,-1717986918 被符号扩展为 64 b,然后转换为无符号 64b,得到 2^64 - 1717986918,仅略小于 2^64,绝对超过您在系统中的内存。

关于C二进制达到1.2G内存限制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31720747/

相关文章:

c++ - 尝试分配最大可能的内存来处理

c - 为什么 Mac OS 上的 C 运行时允许预组合和分解的 UTF-8?

java - 堆转储与可视化虚拟机中的内存分析

c++ - 在 C++ 中重用内存

delphi - 我需要释放列表中的元素吗?

c# - 有没有办法将通用枚举值转换为 UInt64 值而不进行分配?

c - Go 语言使用 C 的内部结构

c - 调用 lseek() 时,POSIX read() 函数不读取任何字节

c - 逐步执行可变长度的整数行

python - 为什么 'VIRT'小于顶部的 'RES'