Reputation: 3693
Just got query regarding c malloc() function. I am read()ing x number of bytes from a file to get lenght of filename, like ' read(file, &namelen, sizeof(unsigned char)); ' .
The variable namelen is a type unsigned char and was written into file as that type (1 byte). Now namelen has the lenght of filename ie namelen=8 if file name was 'data.txt', plus extra /0 at end, that working fine.
Now I have a structure recording file info, ie filename, filelenght, content size etc.
struct fileinfo
{
char *name;
...... other variable like size etc
};
struct fileinfo *files;
Question: I want to make that files.name variable the size of namelen ie 8 so I can successfully write the filename into it, like ' files[i].name = malloc(namelen) '
However, I dont want it to be malloc(sizeof(namelen)) as that would make it file.name[1] as the size of its type unsigned char. I want it to be the value thats stored inside variable &namelen ie 8 so file.name[8] so data.txt can be read() from file as 8 bytes and written straight into file.name[8?
Is there a way to do this my current code is this and returns 4 not 8
files[i].name = malloc(namelen);
//strlen(files[i].name) - returns 4
//perhaps something like
malloc(sizeof(&namelen)) but does not work
Thanks for any suggestions
Have tried suggested suggestions guys, but I now get a segmentation fault error using:
printf("\nsizeofnamelen=%x\n",namelen); //gives 8 for data.txt
files[i].name = malloc(namelen + 1);
read(file, &files[i].name, namelen);
int len=strlen(files[i].name); printf("\nnamelen=%d",len);
printf("\nname=%s\n",files[i].name);
When I try to open() file with that files[i].name variable it wont open so the data does not appear to be getting written inside the read() &files[i].name and strlen() causes segemntation error as well as trying to print the filename
Upvotes: 0
Views: 1864
Reputation: 663
read(file, &files[i].name, namelen);
should be
read(file, files[i].name, namelen);
Because files[i].name stores the address of the allocated buffer. Since the prototype for read is void* your compiler might be letting you get away with passing a char** rather than reporting an error.
Also as maxschlepzig said, don't forget to add a \0 to the end of the buffer.
Upvotes: 0
Reputation: 39047
malloc returns uninitialized memory, thus the result of
strlen(files[i].name)
directly after
files[i].name = malloc(namelen);
is undefined.
And strlen
counts the characters until the first '\0' character in a memory block - it does not return the memory block size allocated by a former malloc
call.
Regarding question update:
A read
does not terminate the destination with a '\0' character, and this is why you get a segmentation fault.
Inserting a
files[i].name[namelen] = '\0';
properly terminates the C-string and should fix this issue.
Alternatively you could use calloc
instead of malloc.
Upvotes: 1
Reputation: 91
Did you allocate space for the files? Currently, it is struct fileinfo * files;
Assuming you did something like this: files = malloc(sizeof(struct fileinfo) * num_files);
printf("\nsizeofnamelen=%x\n",namelen); //gives 8 for data.txt
files[i].name = malloc(namelen + 1);
read(file, &files[i].name, namelen);
files[i].name[namelen] = '\0'; // NUL-terminate the string.
int len=strlen(files[i].name); printf("\nnamelen=%d",len);
printf("\nname=%s\n",files[i].name);
If you don't NUL-terminate the string (file[i].name) then you will keep reading random stuff and possibly segfault.
Upvotes: 0
Reputation: 399703
If the filename won't change, you can be a bit efficient and allocate both the structure and the space for the filename in the same malloc()
:
struct fileinfo *files = malloc(sizeof *files + namelen + 1);
files->name = (char *) (files + 1);
This allocates a single block of memory which is large enough for the struct fileinfo
(i.e. sizeof *files
bytes) and the '\0'-terminated filename (namelen + 1
). The second line make the name
member of the struct point at the first byte after the struct itself.
You can then go ahead and write the filename into files->name
by e.g. loading it with another call to read()
.
You can free the entire structure, including the filename, with a single call to free(files)
when you're done with it.
Upvotes: 1
Reputation: 41306
The code you have is (almost) the correct way to allocate the memory, you need to include space for the trailing NULL byte:
files[i].name = malloc(namelen + 1);
Note that at this point the string is not initialized, so strlen(files[i].name)
will either return a random number of crash. You can use memset()
to zero the memory and then strlen(files[i].name)
will return 0. If you read the data from the file, strlen(files[i].name)
will return 8.
Upvotes: 2
Reputation: 10864
strlen(name) + 1
bytes long (because of the terminating \0
).namelen = strlen("data.txt")
(i.e. 8) then you must allocate files[i].name = malloc(namelen + 1)
malloc()
is undefined. You cannot perform strlen()
on memory you just allocated - you must set the memory you've allocated firststrncpy( files[i].name, "data.txt", namelen + 1 )
and only then can you strlen( files[i].name )
Upvotes: 3