如何理解堆是否已满以及为什么 malloc 保持 return NULL?
How to understand if Heap is full and why malloc keeps return NULL?
作为一个练习,我目前正在做一个项目:一个基于个人文本的数据库(因此是(个人和非)数据的集合,作为一种“数据库”排列在一个文件中),使用 C 编程语言进行管理.
我想将所有管理功能保存在 .h
文件中,将主要功能(与用户、数据库所有者交互的功能)保存在 .c
文件中。
.h
文件还没有完成,但我正在慢慢测试每个功能,看它们是否正常工作。
尤其是这个让我望而生畏,因为我找不到堆满的原因(如果它真的满了......)。
这是完整的代码:(感兴趣的函数称为“initobj”。虽然我分享了完整的代码,但认为它可能有助于理解)
#include <time.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#if defined(_WIN32)
#define PATH "C:\Database\"
#elif defined(_WIN64)
#define PATH "C:\Database\"
#elif defined(__linux__)
#define PATH "/Database/"
#else
#define PATH NULL
#endif
struct user{
unsigned int uid;
char *username;
char *password;
};
struct file{
unsigned int uid;
char *filename;
char *content;
};
char *initpath(void){
char filename[] = "Database.txt";
char *path = (char *)malloc(sizeof(char) * strlen(PATH) + 1);
if(path != NULL){
strcpy(path, PATH);
mkdir(path);
strcat(path, filename);
return path;
}
else
return NULL;
}
int initobj(struct user *elem, unsigned uid, char *username, char *password){
elem->uid = uid;
if((elem->username = (char *)malloc(sizeof(char) * strlen(username) + 1)) != NULL)
strcpy(elem->username, username);
else
return -1;
if((elem->password = (char *)malloc(sizeof(char) * strlen(password) + 1)) != NULL)
strcpy(elem->password, password); //Password is copied into the structure as a normal string. Future updata: encrypting the password
else
return -1;
return 0;
}
int insobj(int database, struct user elem){}
int checkid(int database, unsigned int id){}
int checkusr(int database, char *username){}
int checkpasw(int database, char *password){}
下面是主要功能代码:
#include <time.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "database.h"
struct user playground;
int main(int argc, char *argv[]){
srand(time(0));
int err;
struct user *p = &playground;
char *filepath = initpath();
if(filepath != NULL && argc == 3){
if((err = initobj(p, (rand() % 999), argv[1], argv[2])) == 0)
printf("%u, %s, %s <- Data inserted.\n", p->uid, p->username, p->password);
else
printf("[DEBUG]: From function 'initobj' : %d.\n", err);
}
else
fprintf(stderr, "%s: Not enought arguments.\n", argv[0]);
}
程序让return我-1:
C:\Users\Computer\Desktop\ACCESS\Database\lib>dat username password
[DEBUG]: From function 'initobj' : -1.
因此意味着 malloc 无法在头部分配 space。我只是不明白为什么。
至少这些问题:
代码未能分配足够的 space @
强尼莫普
char filename[] = "Database.txt";
char *path = (char *)malloc(sizeof(char) * strlen(PATH) + 1); // Wrong size & sense
if(path != NULL){
strcpy(path, PATH);
mkdir(path);
strcat(path, filename); // !! Undefined behavior (UB) !!
return path;
}
有了strcat(path, filename);
的UB,其余代码无关
相反
同时考虑 PATH
和 filename
不需要转换。
缩放 sizeof(char) * strlen(PATH) + 1
应该是 sizeof(char) * (strlen(PATH) + 1)
。 sizeof(char)
为 1,也不需要。
char filename[] = "Database.txt";
// PATH filename minus its [=11=] [=11=]
char *path = malloc(strlen(PATH) + (sizeof filename - 1) + 1);
mkdir()
可能会失败
更好的代码将测试 mkdir()
成功。
if (mkdir(path)) {
Handle_failure();
}
作为一个练习,我目前正在做一个项目:一个基于个人文本的数据库(因此是(个人和非)数据的集合,作为一种“数据库”排列在一个文件中),使用 C 编程语言进行管理.
我想将所有管理功能保存在 .h
文件中,将主要功能(与用户、数据库所有者交互的功能)保存在 .c
文件中。
.h
文件还没有完成,但我正在慢慢测试每个功能,看它们是否正常工作。
尤其是这个让我望而生畏,因为我找不到堆满的原因(如果它真的满了......)。
这是完整的代码:(感兴趣的函数称为“initobj”。虽然我分享了完整的代码,但认为它可能有助于理解)
#include <time.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#if defined(_WIN32)
#define PATH "C:\Database\"
#elif defined(_WIN64)
#define PATH "C:\Database\"
#elif defined(__linux__)
#define PATH "/Database/"
#else
#define PATH NULL
#endif
struct user{
unsigned int uid;
char *username;
char *password;
};
struct file{
unsigned int uid;
char *filename;
char *content;
};
char *initpath(void){
char filename[] = "Database.txt";
char *path = (char *)malloc(sizeof(char) * strlen(PATH) + 1);
if(path != NULL){
strcpy(path, PATH);
mkdir(path);
strcat(path, filename);
return path;
}
else
return NULL;
}
int initobj(struct user *elem, unsigned uid, char *username, char *password){
elem->uid = uid;
if((elem->username = (char *)malloc(sizeof(char) * strlen(username) + 1)) != NULL)
strcpy(elem->username, username);
else
return -1;
if((elem->password = (char *)malloc(sizeof(char) * strlen(password) + 1)) != NULL)
strcpy(elem->password, password); //Password is copied into the structure as a normal string. Future updata: encrypting the password
else
return -1;
return 0;
}
int insobj(int database, struct user elem){}
int checkid(int database, unsigned int id){}
int checkusr(int database, char *username){}
int checkpasw(int database, char *password){}
下面是主要功能代码:
#include <time.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "database.h"
struct user playground;
int main(int argc, char *argv[]){
srand(time(0));
int err;
struct user *p = &playground;
char *filepath = initpath();
if(filepath != NULL && argc == 3){
if((err = initobj(p, (rand() % 999), argv[1], argv[2])) == 0)
printf("%u, %s, %s <- Data inserted.\n", p->uid, p->username, p->password);
else
printf("[DEBUG]: From function 'initobj' : %d.\n", err);
}
else
fprintf(stderr, "%s: Not enought arguments.\n", argv[0]);
}
程序让return我-1:
C:\Users\Computer\Desktop\ACCESS\Database\lib>dat username password
[DEBUG]: From function 'initobj' : -1.
因此意味着 malloc 无法在头部分配 space。我只是不明白为什么。
至少这些问题:
代码未能分配足够的 space @ 强尼莫普
char filename[] = "Database.txt";
char *path = (char *)malloc(sizeof(char) * strlen(PATH) + 1); // Wrong size & sense
if(path != NULL){
strcpy(path, PATH);
mkdir(path);
strcat(path, filename); // !! Undefined behavior (UB) !!
return path;
}
有了strcat(path, filename);
的UB,其余代码无关
相反
同时考虑
PATH
和filename
不需要转换。
缩放
sizeof(char) * strlen(PATH) + 1
应该是sizeof(char) * (strlen(PATH) + 1)
。sizeof(char)
为 1,也不需要。char filename[] = "Database.txt"; // PATH filename minus its [=11=] [=11=] char *path = malloc(strlen(PATH) + (sizeof filename - 1) + 1);
mkdir()
可能会失败
更好的代码将测试 mkdir()
成功。
if (mkdir(path)) {
Handle_failure();
}