我前几天编写了一个小程序来处理单词搜索,发现为 bianry搜索树分配内存,我存储了我试图分析的每个单词,使用malloc()
,我的4G内存将被快速耗尽。
我的程序中没有内存韭菜,因为我只为该二进制搜索树分配内存。但是,我仍然可以在程序中分配少于6000个二叉搜索树。该二叉搜索树的结构是:
typedef struct BSTnode{
char data[20];
struct BSTnode* leftchild;
struct BSTnode* rightchild;
int num;
}BSTnode;
所以它很小。根据我所学到的,每个结构都需要80字节的内存(data
需要20个字节,因为内存对齐也是如此)(对吗?)
6000内存中的结构总共需要花费480MB。
然而,当我尝试为6000个结构分配内存时,我的程序失败了(当我为 5000 分配内存时可以。)我的PC总共有4 GB的内存! (大约有1000MB cached
,2100MB available
和1100MB free
(根据Windows上的任务经理))。
为什么?
我主要担心的是:
为什么?
如何在我的程序中优雅地管理内存分配。
您能提供更多信息吗?(引用,示例和书籍等)
(顺便说一句,如果你想查看我的代码,请在下面留下评论。行数太多,花一些时间让它更具可读性。抱歉)
################################################## ################## 3代码:
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<string.h>
typedef struct Node
{
struct Node* leftChild;
struct Node* rightChild;
char data[20];
int num;
} Node;
int inputWord(FILE*, Node*);
int main(int argc, char** argv)
{
printf("Enter the name of file you wanna open here:");
char name[20] =
{ '\0' };
scanf("%s", name);
FILE* fs = fopen(name, "r");
if (!fs)
{
perror("Failed to open file!");
exit(EXIT_FAILURE);
}
Node* firstNode = malloc(sizeof(Node));
if (firstNode == NULL )
{
perror("ALLOCATION FAILED!");
exit(1);
}
firstNode->leftChild = firstNode->rightChild = NULL;
firstNode->num = 1;
strcpy(firstNode->data, "a");
inputWord(fs, firstNode);
fclose(fs);
printf("Done!!");
return 0;
}
int inputWord(FILE* fs, Node* firstNode)
{
rewind(fs);
/*first figure out a single word, and then put it into to BST*/
int flag_1 = 0;
char buf = '\0';
char word[20] =
{ '\0' };
Node* ptrOfNode = firstNode;
int numOfWord = 0;
while (1)
{
if (numOfWord < 2000)
{ //amend this number to determine how many word to be input
if (1 != fread(&buf, 1, 1, fs))
{
perror("failed to read file or eof\n");
}
if (!isalpha(buf))
continue;
/*this while loop is used to picked out a single word in the text*/
while (flag_1 == 0)
{
strncat(word, &buf, 1);
if (1 != fread(&buf, 1, 1, fs))
{
perror("Failed to read char from the file");
exit(2);
}
if (isalpha(buf))
flag_1 = 0;
else
flag_1 = 1; //now buf is not alpha
}
flag_1 = 0;
while (1)
{
if (stricmp(word, ptrOfNode->data) > 0&& ptrOfNode->rightChild!=NULL)
ptrOfNode = ptrOfNode->rightChild;
else if (stricmp(word, ptrOfNode->data) < 0 && ptrOfNode->leftChild!=NULL)
ptrOfNode = ptrOfNode->leftChild;
else
break;
}
/*the while loop above break for only two reason:
*1.there have been an identical word in the tree;
*2.the child where I want to insert the word have not been allocated memory
*/
if (stricmp(word, ptrOfNode->data) == 0)
{
++(ptrOfNode->num);
memset(word, '\0', 20);
ptrOfNode = firstNode; //move the pointer of Node to the very first
numOfWord+=1;
continue;
}
else
{
if (stricmp(word, ptrOfNode->data) > 0)
{ //mean that there is no more right child
ptrOfNode->rightChild = malloc(sizeof(Node));
if (ptrOfNode->rightChild == NULL )
{
perror("FAILED TO ALLOCATED MEMORY!!");
exit(1);
}
ptrOfNode = ptrOfNode->rightChild;
ptrOfNode->leftChild = ptrOfNode->rightChild = NULL;
ptrOfNode->num = 1;
strcpy(ptrOfNode->data, word);
memset(word, '\0', 20);
ptrOfNode = firstNode;
numOfWord += 1;
continue;
}
else
{
ptrOfNode->leftChild = malloc(sizeof(Node));
if (ptrOfNode->leftChild == NULL )
{
perror("FAILED TO ALLOCATE MEMORY!");
exit(1);
}
ptrOfNode = ptrOfNode->leftChild;
ptrOfNode->leftChild = ptrOfNode->rightChild = NULL;
ptrOfNode->num = 1;
strcpy(ptrOfNode->data, word);
memset(word, '\0', 20);
ptrOfNode = firstNode;
numOfWord += 1;
continue;
}
}
}
else
break;
}
return 0;
}
我写的另一个程序可以绝对解释我的问题。但这太长了以至于我无法让所有人都阅读并将其发布在此处。[1] https://github.com/walkerlala/searchText
如果你不认为这是一个适合这个问题的程序(我链接中的那个绝对是),请考虑我上面的问题。
答案 0 :(得分:0)
我写了一些简单的代码来模拟你的问题。
struct Node{
int val;
Node *left;
Node *right;
Node() :val(1){}
};
int main(){
int size = sizeof(Node);//size = 12Bytes
const int N = 10e5;
const int factor = 5;//12B*5*10^5 = 6MB
Node* ptrArr[factor];
//Test 1, costs 57MB!
for (int i = 0; i < factor; i++){
ptrArr[i] = new Node[N];
}
//Test 2, costs 348MB!
/*
for (int i = 0; i < N*factor; i++){
Node *temp = new Node;
}*/
return 0;
}
我们希望分配5*10e5
* Node
s,理论上,它会花费12Bytes * 5 * 10e5 = 6MB
。
我在VS2013
中运行此代码,Test 1
费用为57MB
,而Test 2
费用为348MB
!
回到你的问题,为什么会这样?
一个原因是片段,另一个原因是保留内存。
如果您打开DEBUG->WINDOWS->MEMORY
并查看ptrArr[i]
的地址,您会发现在用于保存Node
的内存之后,有相当大的未使用区域存储器中。
例如,ptrArr[0] = 0x00b18040
和ptrArr[1] = 0x0169f040
。 0x0169f040 - 0x00b18040 = 0xb87000 = 12087296 Bytes ≈ 12*10e6 Bytes
因此,Visual Studio分配的内存比我们需要的多10倍。
Test 2
怎么样?一次分配较小的内存,更多的内存碎片。
如何在我的程序中优雅地管理内存分配?
更多信息。
std::vector
的增加情况吗?std::vector<int> numbers;
当我们一次推送一个号码时,numbers
的容量会改变如下:1->2->3->4->6->9->13->19->...->n->(n+n/2)->...