A
Anton Nørgaard
Guest
Anton Nørgaard Asks: Why does this method for reading in a value from a file in C causes a segfault?
The background for my problem
I am presently writing a video game in C as a personal project. Due to the increasing number of hard-coded values, it was becoming impractical to store them directly inside the source code. Instead, it was decided that the values should be stored in files and then be dynamically read in, when relevant. Several options were available for this, but all of them were too tedious to set up and overkill for the desired usage. Therefore, I decided to write my own implementation of a file reader that returns values stored in files.
Initial approach to the solution
To make my code as generalizeable as possible, it was decided that the strategy i.e function that reads the file and returns the value, should first of all, return a void pointer, because it can store arbitrary values. The way that you then retrieved a value from a specific file, was that you would provide an argument specifying the desired type of the return value e.g by using an enum. The function would then based on the enum, store the value as the corresponding data type in the void pointer and it would be your responsibility to cast the returned void pointer to the correct type.
Expected file format
The files that the code should read, would be simple text files. The files in question, would consist of lines of variable names with a value assigned to them. Here is an example of how a file for my project would look like.
So for example, the variable name would have the char* value of "main_character", the variable money would have the int value of 1000 and damage_multiplier, the float value of 1.2
Current code
Obviously including the entire code repository of my game won't be useful, so instead I have attempted to the best of my abilities to provide a minimum reproducible example.
We define the enum Return_Type that we pass as an argument to the function in order to retrieve a variable as a specific type
So if we want to return a variable as an integer, we pass the value integer to the method
The file i am presently trying to read from is a file that represents a creature struct. Its contents looks like this.
The method used to read the file is this function
For sake of readability, I have reduced the function to only consider the case when we want to retrieve the variable as an integer.
For the minimum reproducible example, i am trying to read the variable species from the file and i want it to be retrieved as an integer
I would have gone on to demonstrate all the different approaches I have tried to remedy the problem, but I feel that this question is already dragging on quite a bit. I have tried approaches like passing a void pointer as an argument and store the value in that instead, I have tried to return the value as a char pointer, return the value in a union and so on. None of the approaches work. I feel like there is some subtlety in reading files that I haven't caught up on yet. Can you pinpoint me as to what the error is?
The background for my problem
I am presently writing a video game in C as a personal project. Due to the increasing number of hard-coded values, it was becoming impractical to store them directly inside the source code. Instead, it was decided that the values should be stored in files and then be dynamically read in, when relevant. Several options were available for this, but all of them were too tedious to set up and overkill for the desired usage. Therefore, I decided to write my own implementation of a file reader that returns values stored in files.
Initial approach to the solution
To make my code as generalizeable as possible, it was decided that the strategy i.e function that reads the file and returns the value, should first of all, return a void pointer, because it can store arbitrary values. The way that you then retrieved a value from a specific file, was that you would provide an argument specifying the desired type of the return value e.g by using an enum. The function would then based on the enum, store the value as the corresponding data type in the void pointer and it would be your responsibility to cast the returned void pointer to the correct type.
Expected file format
The files that the code should read, would be simple text files. The files in question, would consist of lines of variable names with a value assigned to them. Here is an example of how a file for my project would look like.
Code:
name=main_character
money=1000
damage_multiplier=1.2
So for example, the variable name would have the char* value of "main_character", the variable money would have the int value of 1000 and damage_multiplier, the float value of 1.2
Current code
Obviously including the entire code repository of my game won't be useful, so instead I have attempted to the best of my abilities to provide a minimum reproducible example.
We define the enum Return_Type that we pass as an argument to the function in order to retrieve a variable as a specific type
Code:
typedef enum{integer, string, floating,struct_limb,struct_attributes}Return_Type;
So if we want to return a variable as an integer, we pass the value integer to the method
The file i am presently trying to read from is a file that represents a creature struct. Its contents looks like this.
Code:
species=0
name=Short-faced bear
representation=a
id=0
limb_count=7
limbs=[[0,0,100,100],[1,0,100,100],[2,0,100,100],[2,0,100,100],[3,0,100,100],[3,0,100,100],[4,0,100,100]]
weight=900
height=3.4
attributes=[12,12,12,12,12,12,12,12]
max_health=100
max_carry=100
preferred_attack_type=1
The method used to read the file is this function
Code:
void *ir_readin_data(char *file_path, char *variable, Return_Type expected_type){
void *value;
FILE *fp = fopen(file_path, "r");
char * line = NULL;
size_t len = 0;
while((getline(&line, &len, fp)) != -1){
char *variable_pointer = strstr(line, variable);
if(variable_pointer != NULL){
char *value_as_str = strtok(strchr(line, '=')+1, "\n");
if(expected_type == integer){
/*Deprecated, but still used for sake of ease, strtol doesn't
work either */
int value_as_integer = atoi(value_as_str);
value = &value_as_integer;
fclose(fp);
return value;
}
}
}
}
For sake of readability, I have reduced the function to only consider the case when we want to retrieve the variable as an integer.
For the minimum reproducible example, i am trying to read the variable species from the file and i want it to be retrieved as an integer
Code:
*(int *)ir_readin_data(creature_file_path,"species", integer);
I would have gone on to demonstrate all the different approaches I have tried to remedy the problem, but I feel that this question is already dragging on quite a bit. I have tried approaches like passing a void pointer as an argument and store the value in that instead, I have tried to return the value as a char pointer, return the value in a union and so on. None of the approaches work. I feel like there is some subtlety in reading files that I haven't caught up on yet. Can you pinpoint me as to what the error is?
SolveForum.com may not be responsible for the answers or solutions given to any question asked by the users. All Answers or responses are user generated answers and we do not have proof of its validity or correctness. Please vote for the answer that helped you in order to help others find out which is the most helpful answer. Questions labeled as solved may be solved or may not be solved depending on the type of question and the date posted for some posts may be scheduled to be deleted periodically. Do not hesitate to share your thoughts here to help others.