Reputation: 13
So my problem right now is that for some reason, I designate a pointer as NULL
in the first function to be called, but then when I check it later, it's not NULL
anymore.
So I have a few structs, detailed here:
#include <stdio.h>
typedef struct filenode {
struct filenode *next, *prev;
const char *name;
} Filenode;
typedef struct foldernode {
struct foldernode *next, *root, *subdir, *prev;
Filenode *filenodes;
const char *name;
} Folders;
typedef struct Filesystem {
Folders *current;
} Filesystem;
And then I go to my actual file, where I initialize the Filesystem
.
This is the initialization function:
void mkfs(Filesystem *files) {
/* Initializes space for the filesystem itself */
files = malloc(sizeof(*files));
if(files == NULL) {
printf("Memory allocation failed!\n");
return;
}
/* Initializes space for the first root node */
files->current = malloc(sizeof(files->current));
if(files->current == NULL) {
printf("Memory allocation failed!\n");
return;
}
files->current->filenodes = NULL;
}
Now, when I go into the next function, mkdir, and I check if files->current->filenodes = NULL
, and it is not NULL
anymore. I'm extremely confused right now. And yes, the same *files
variable is being passed in to every function.
Upvotes: 1
Views: 332
Reputation: 724
Just to correct the answers below/above - Instead of doing
Type *pType;
pType = (Type *) malloc (sizeof (pType)); // <- the size allocated is for a pointer
What you want to do is
Type *pType;
pType = (Type *) malloc (sizeof (*pType)); // <- now allocates space for Type!
This is a common mistake...
Upvotes: 0
Reputation: 22125
From the comments, you say you can't change the signature of mkfs()
. I'm going to assume it's called like this:
Filesystem files;
mkfs(&files);
If that's the case, you don't need to create space for the structure (since it's created on the stack just before your mkfs()
call), so you can remove this line:
files = malloc(sizeof(*files));
Removing this line will fix the problem that you can't see the changes to files
after the function has returned. This was causing you trouble since C is always pass by value - the malloc was changing the value of the local copy of the files
pointer, meaning that no further changes were seen outside your function.
You will also run into trouble with this line:
files->current = malloc(sizeof(files->current));
Since files->current
is a pointer to a struct foldernode
, the sizeof call only tells you the size of the pointer. You probably meant:
files->current = malloc(sizeof(struct foldernode));
or:
files->current = malloc(sizeof(Folders));
Upvotes: 2
Reputation: 124642
void mkfs(Filesystem *files)
Here the pointer files
is passed by copy. This is not the pointer you declared and passed to the function, but instead a copy of that pointer which points to the same memory location. The pointers themselves reside in different memory locations.
files = malloc(sizeof(*files));
Here you assign a new value to the pointer files
. However, this is again just a copy of the original pointer. So you give the copy a new value, but the original pointer remains unchanged.
If you need to assign a new value to the argument itself (not simply mutate what it points to, but actually assign a new value to it) then you need to pass a pointer to pointer.
void mkfs(Filesystem **files) {
/* Initializes space for the filesystem itself */
*files = malloc(sizeof(Filesystem));
/* ... */
}
Upvotes: 1
Reputation: 881443
And yes, the same "*files" variable is being passed in to every function.
as a copy of the real variable which won't be reflected back to the caller.
Your mkfs
is broken. It assigns the result of malloc
to the local copy of files
, which is then tossed away on exit.
You will need something like:
void mkfs(Filesystem **pFiles) {
/* Initializes space for the filesystem itself */
*pFiles = malloc(sizeof(FileSystem));
if(*pfiles == NULL) {
printf("Memory allocation failed!\n");
return;
}
/* Initializes space for the first root node */
(*pFiles)->current = malloc(sizeof((*pfiles)->current));
if((*pFiles)->current == NULL) {
printf("Memory allocation failed!\n");
free (*pFiles); // <-- to avoid memory leaks
return;
}
(*pFiles)->current->filenodes = NULL;
}
and to call it with:
FileSystem *files;
mkfs (&files);
By passing in a pointer to the pointer, you can reflect any changes back to the original. This scheme should be used for any variable you want to change in a function and have reflected back.
Now you may think you're already doing that because you're passing in a pointer but, when it's the actual pointer that you want to change, you need the double-pointer.
You'll also notice that I've added a free
call to free the first allocation if the second fails. That's needed to avoid memory leaks.
Upvotes: 1