As an exercise, currently I am working on a project: a personal text based database (hence a collection of (personal and not) data arranged in a file as a sort of "database") managed with C programming Language.
I thought to keep all the managing function on a .h
file and the main functions (the one that interact with the user, owner of the database) in a .c
file.
The .h
file is not completed yet, but I am slowly testing each function to see if they work correctly.
In particular this one it is daunting me duo to the fact I cannot find the reason why heap gets full (if it really gets full...).
Here is the full code: (The interested function is called "initobj". Though I shared the full code thinking it could be useful to understand)
#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){}
Here instead is the main function code:
#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]);
}
The program keeps return me -1:
C:\Users\Computer\Desktop\ACCESS\Database\lib>dat username password
[DEBUG]: From function 'initobj' : -1.
Hence means malloc is not able to allocate space in head. I just don't understand why.
CodePudding user response:
At least these issues:
Code fails to allocate sufficient space @ Johnny Mopp
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;
}
With the UB of strcat(path, filename);
, rest of code is irrelevant.
Instead
Account for both
PATH
andfilename
Cast not needed.
Scaling by
sizeof(char) * strlen(PATH) 1
should have beensizeof(char) * (strlen(PATH) 1)
.sizeof(char)
is 1 and is not needed either.char filename[] = "Database.txt"; // PATH filename minus its \0 \0 char *path = malloc(strlen(PATH) (sizeof filename - 1) 1);
mkdir()
may fail
Better code would test mkdir()
success.
if (mkdir(path)) {
Handle_failure();
}