C二进制达到1.2G内存限制
C binary reaches 1.2G memory limit
我正在处理一个 C 程序,它从一个文件中读入许多
每行约 60 个字符,并在内存中分配字符串
通过在读取文件时请求更多内存。在每个 malloc
之后
请求,它会检查函数 OOM()
是否请求更多
记忆成功。
我用越来越大的输入文件测试了程序,并且
OOM()
报告一个 "Out of memory"
或多或少当记忆
在程序中查看top
命令时使用量达到1.2G
运行宁。这是在具有更多内存的 64 位 linux 机器上
可用的。 file /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,巧合的是我在这里看到的。
当我运行qsub
在同一个64bit的节点上执行同一个Linux
SGE 网格保留 50GB 的内存,它报告也 "Out of
memory"
和以下 SGE 日志内存占用:
Max vmem = 2.313G
知道为什么程序会达到此内存限制吗?有没有
我应该知道哪些编译标志可以 cause/solve 这个?
在当前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
部分相关代码belo: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 程序,它从一个文件中读入许多
每行约 60 个字符,并在内存中分配字符串
通过在读取文件时请求更多内存。在每个 malloc
之后
请求,它会检查函数 OOM()
是否请求更多
记忆成功。
我用越来越大的输入文件测试了程序,并且
OOM()
报告一个 "Out of memory"
或多或少当记忆
在程序中查看top
命令时使用量达到1.2G
运行宁。这是在具有更多内存的 64 位 linux 机器上
可用的。 file /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,巧合的是我在这里看到的。
当我运行qsub
在同一个64bit的节点上执行同一个Linux
SGE 网格保留 50GB 的内存,它报告也 "Out of
memory"
和以下 SGE 日志内存占用:
Max vmem = 2.313G
知道为什么程序会达到此内存限制吗?有没有 我应该知道哪些编译标志可以 cause/solve 这个?
在当前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
部分相关代码belo: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,并且肯定比你系统内存多。