Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Using Item from Hashmap causes segmentation fault

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

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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?

>Solution :

    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.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading