Reputation: 15
I want some function (save()
) to get a pointer to array of structures dbEntry
and fill it with data. This is where memory management issues come in.
This is my code:
Structure itself:
typedef struct dbEntry {
unsigned int id;
char* type;
char* name;
unsigned int parent_id;
unsigned char* md5;
} dbEntry;
Memory allocation and calling save()
:
int main(int argc, char const* argv[]){
if (argc != 5) arg_error();
if (strcmp(argv[1], "-s") == 0){
FILE* database = fopen(argv[2], "wb");
if (database == NULL) file_error();
dbEntry* entries = malloc(150*sizeof(dbEntry*));
for (int i=0; i<150; i++){
entries[i].id = 0;
entries[i].parent_id = 0;
entries[i].name = malloc(50*sizeof(char));
entries[i].type = malloc(10*sizeof(char));
entries[i].md5 = malloc(MD5_DIGEST_LENGTH*sizeof(unsigned char));
}
int entry_num = save(argv[4], 0, &entries);
save()
int save(char* dir_path, unsigned int parent, dbEntry** entries) {
size_t path_len = strlen(dir_path);
if (dir_path[path_len - 1] != '/') strcat(dir_path, "/");
char dp_copy[path_len];
strcpy(dp_copy, dir_path);
DIR* dir = opendir(dir_path);
struct dirent* dirent = readdir(dir);
dirent = readdir(dir);
dirent = readdir(dir);
unsigned int id = 0;
char* fpath;
if (dirent == NULL) {
fprintf(stderr,
"Directory %s doesn't exist or can't be "
"opened. Check permissions\n",
dir_path);
exit(-1);
}
while (dirent != NULL) {
entries[id]->id = id;
strcpy(entries[id]->name, dirent->d_name);
entries[id]->parent_id = parent;
if (dirent->d_type == 8) {
strcpy(entries[id]->type, "file");
size_t len = strlen(dir_path)+strlen(dirent->d_name);
fpath = malloc(len);
strcpy(fpath, dir_path);
strcat(fpath, dirent->d_name);
FILE* file = fopen(fpath, "rb");
if (file == NULL){
printf("Could not open file %s for reading\n", fpath);
exit(-1);
}
md5digest(file, entries[id]->md5);
fclose(file);
printf("Saved %s\n", strcat(dir_path, dirent->d_name));
GDB output:
57 while (dirent != NULL) {
(gdb) n
58 entries[id]->id = id;
(gdb) n
59 strcpy(entries[id]->name, dirent->d_name);
(gdb) n
60 entries[id]->parent_id = parent;
(gdb) n
62 if (dirent->d_type == 8) {
(gdb) n
63 strcpy(entries[id]->type, "file");
(gdb) n
64 size_t len = strlen(dir_path)+strlen(dirent->d_name);
(gdb) n
65 fpath = malloc(len);
(gdb) n
66 strcpy(fpath, dir_path);
(gdb) n
67 strcat(fpath, dirent->d_name);
(gdb) p entries
$1 = (dbEntry **) 0x7ffffffee110
(gdb) p entries[0]
$2 = (dbEntry *) 0x8403490
(gdb) p entries[1]
$3 = (dbEntry *) 0x0
(gdb) p entries[2]
$4 = (dbEntry *) 0x8403260
(gdb) p entries[3]
$5 = (dbEntry *) 0xf625f4cc70b40b00
(gdb) p entries[4]
$6 = (dbEntry *) 0x7ffffffee220
(gdb) p entries[5]
$7 = (dbEntry *) 0x0
(gdb) p entries[6]
$8 = (dbEntry *) 0x8001890 <__libc_csu_init>
(gdb) p entries[7]
$9 = (dbEntry *) 0x7ffffeb51b97 <__libc_start_main+231>
(gdb) p entries[8]
$10 = (dbEntry *) 0x2000000000
(gdb) p entries[0]->name
$11 = 0x8403950 ".bash_history"
(gdb)
For some reason, it failed to allocate memory for entries[1]
, entries[5]
and some more, so the program returns Address boundary error
when trying to reference entries[1]
.
Tried almost everything, but the issue persists. Looking for your help.
Upvotes: 0
Views: 173
Reputation: 409166
You have two problems:
With
malloc(150*sizeof(dbEntry*))
you allocate memory for 150 pointers to dbEntry
structures, not
the dbEntry
structures themselves.
I recommend that you get the size of the data to allocate from the variable itself, as in:
dbEntry *entries = malloc(150 * sizeof *entries);
In the save
function the variable entries
is essentially a pointer to an array of dbEntry
structures. You treat it as an array of pointers to structures (a pointer to an array is not the same as an array of pointers). You need to dereference the pointer to get the original pointer, which can then be dereferenced like an array of structures:
(*entries)[id].id = id;
Or simply not pass it as a pointer to a pointer:
// Note only one asterisk
// v
int save(char* dir_path, unsigned int parent, dbEntry* entries) {
...
entries[id].id = id; // Entries can be treated like a normal array of structures
...
}
Upvotes: 1