Reputation: 141
I am trying to fill a hashmap of Spritesheets. The data for the Spritesheet is read from a json file.
I am using hashmap.c for the hashmap and cJSON for parsing the json data
The SpriteSheet struct
typedef struct
{
char* name;
char* path;
int width;
int height;
} SpriteSheet;
Example Json Data
"spriteSheets": [
{
"name": "player",
"path": "player.png",
"width": 192,
"height": 64
}
]
The Code
spriteSheetHashMap = hashmap_new(sizeof(SpriteSheet), 0, 0, 0, spriteSheetHash, spriteSheetCompare, NULL, NULL);
cJSON* textureJson = cJSON_Parse(textureJsonString);
cJSON* spriteSheetsJson = cJSON_GetObjectItemCaseSensitive(textureJson, "spriteSheets");
cJSON* spriteSheetJson;
cJSON_ArrayForEach(spriteSheetJson, spriteSheetsJson)
{
char* sheetName = cJSON_GetObjectItemCaseSensitive(spriteSheetJson, "name")->valuestring;
char* sheetPath = cJSON_GetObjectItemCaseSensitive(spriteSheetJson, "path")->valuestring;
int sheetWidth = cJSON_GetObjectItemCaseSensitive(spriteSheetJson, "width")->valueint;
int sheetHeight = cJSON_GetObjectItemCaseSensitive(spriteSheetJson, "height")->valueint;
hashmap_set(spriteSheetHashMap, &(SpriteSheet){
.name=sheetName,
.path=sheetPath,
.width=sheetWidth, .height=sheetHeight,
.spriteHashMap=spriteHashMap
});
}
cJSON_Delete(textureJson);
When I access this in some other file, I get a segmentation fault
SpriteSheet* spriteSheet = hashmap_get(spriteSheetHashMap, &(SpriteSheet){ .name="map" });
printf("%s, %s", spriteSheet->name, spriteSheet->path); // This line causes the segmentation fault
But, If I add the items explicitly, it doesn't segfault and prints the values
hashmap_set(spriteSheetHashMap, &(SpriteSheet){
.name="map",
.path="image.png",
.width=4, .height=8
});
// OR
char* a = "map";
char* b = "image.png";
hashmap_set(spriteSheetHashMap, &(SpriteSheet){
.name=a,
.path=b,
.width=4, .height=8
});
Why is this happening? How can I fix it?
Upvotes: 0
Views: 45
Reputation: 182743
char* sheetName = cJSON_GetObjectItemCaseSensitive(spriteSheetJson, "name")->valuestring;
char* sheetPath = cJSON_GetObjectItemCaseSensitive(spriteSheetJson, "path")->valuestring;
The two lines of code above get pointers to parts of spriteSheetJson
.
hashmap_set(spriteSheetHashMap, &(SpriteSheet){
.name=sheetName,
.path=sheetPath,
.width=sheetWidth, .height=sheetHeight,
.spriteHashMap=spriteHashMap
});
The line of code above saves those pointers.
cJSON_Delete(textureJson);
But this line of code above deletes the object that those pointers pointed into. They now point to where the JSON object's data used to be.
SpriteSheet* spriteSheet = hashmap_get(spriteSheetHashMap, &(SpriteSheet){ .name="map" });
printf("%s, %s", spriteSheet->name, spriteSheet->path); // This line causes the segmentation fault
This code tries to dereference the pointers you saved, pointers that pointed to parts of an object that no longer exists.
You need to make copies of the data. The easiest way is to call strdup
on the values returned by cJSON_GetObjectItemCaseSensitive
. Then they're yours to free
when you are done.
Upvotes: 3