Reputation: 5695
I'm working on the following function to pull scripts into my C application:
char *anne_script_load(char fileName[]){
char path[6400] = "data/scripts/";
strncat(path, fileName, 6000);
strncat(path, ".lua", 5);
struct stat fileInfo;
char *contents = NULL;
FILE * pFile;
stat(path, &fileInfo);
contents = (char*)malloc(fileInfo.st_size);
pFile = fopen (path,"r");
fread (contents,1,fileInfo.st_size,pFile);
fclose(pFile);
printf("Script path: %s\n", path);
printf("Script loaded: %s\n", contents);
return contents;
}
At runtime, the second printf
generates the following output:
test script - if you see this load is working :) helicopters����
The garbled text looks different on my console, but I'm not sure it matters: my theory is that the file stream doesn't end in a null byte (it's not stored on disk as a c string
, after all - so I terminated it myself as follows:
contents[fileInfo.st_size] = 0;
This appears to work, but I'm concerned about the robustness of this solution. Is there a better, generally accepted way of doing this?
Upvotes: 0
Views: 948
Reputation: 3009
You must nul-terminated the string otherwise printf()
will not know for sure when to stop reading from the pointer you just passed. The same applies to other functions like strcmp()
, you could have two strings with the same content while having strcmp()
yelling non-zero because of a non nul-terminated string.
So contents[fileInfo.st_size] = 0;
is just fine.
You could read a little bit more about nul-terminated strings on Wikipedia
Upvotes: 1
Reputation: 7054
You need to add +1 to your malloc for the termination:
if(stat(path, &fileInfo) != 0) {
perror("stat");
...
}
contents = (char*)malloc(fileInfo.st_size + 1); // don't forget this
pFile = fopen (path,"r");
if(pFile == 0) {
perror("fopen");
...
}
int n = fread (contents,1,fileInfo.st_size,pFile);
if(n != fileInfo.st_size) {
perror("read");
...
}
contents[n] = 0; // terminate after what you read. Not what you think you read.
** Check the return values from fopen, stat, and read.**
Upvotes: 3
Reputation: 2110
There are number of things you could probably improve here... but to answer your question, fread() is reading bytes into an array that you didn't initialize. In C, you can't expect a \0 character after the last byte you read via fread -- you've got to put it there first, either with a memset() or calloc().
Also, if the file content is treated as a text string, be sure to allocate one additional byte over the size to hold that terminating \0 character!
Upvotes: 1