meshanda
meshanda

Reputation: 29

C: Segmentation fault, why and how to fix


I'm currently learning how to program and i'm pretty sure my code is filled with errors.
I have a segmentation fault when executing this code and i don't know why.

#include <stdio.h>
#include <libxml/parser.h>
#include <string.h>
#include <stdlib.h>


typedef struct
{
        int ac; /**< The player armor class. */
        char *class; /**< The player class. */
        char *cname; /**< The player character name. */
        int cp; /**< The player money (copper pieces, 100 CP = 1 GP). */
        int gp; /**< The player money (gold pieces). */
        int hp; /**< The player hit points. */
        char *name; /**< The player name. */
        int sp; /**< The player money (silver pieces, 10 SP = 1 GP). */
} player_t;

void parsePlayer(xmlDocPtr doc, xmlNodePtr node){
    int i = 1;
    player_t players[3];
    xmlNodePtr cur;

    node = node->xmlChildrenNode;

    while(node!=NULL){
        if (!xmlStrcmp(node->name, (const xmlChar *) "player"))
        {
            players[i].name = (char *) xmlGetProp(node, (const xmlChar *)"name");
            printf("player %d name: %s\n", i, players[i].name);
            cur = node->xmlChildrenNode;
            players[i].ac = strtol((char *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1),NULL,10);
            i++;
        }

        node = node->next;
    }
}

void parsePlayers(xmlDocPtr doc){
    xmlNodePtr node;

    node = xmlDocGetRootElement(doc);

    node = node->xmlChildrenNode; 

    while(node!=NULL){
        if (!xmlStrcmp(node->name, (const xmlChar *) "players")){
            parsePlayer(doc, node);
        }
        node = node->next;
    }
}

int main(int argc, char const *argv[]) {

    xmlDocPtr doc = xmlParseFile(argv[1]);

    if (doc != NULL) printf("DEBUG: File parsed.\n");   
    else { 
        fprintf(stderr,"Unable to parse the document \n");
        return 1;
    }

    parsePlayers(doc);
    return 0;
}

The code display this :

DEBUG: File parsed.
player 1 name: Camille /* correct */
Segmentation Fault

I've tried looking for answers but it seems i'm not advanced enough to understand them :/.
This is for a project in school (i have to fill several player_t structures).
I don't think the error comes from the XML so no need to post it here.
I've been stuck on this error for a few days now and i'd love to understand how to correct it.
Thanks for reading :).

EDIT: Thanks for your answer, gdb says :

Program received signal SIGSEGV, Segmentation fault.
__GI_____strtol_l_internal (nptr=0x0, endptr=0x0, base=10, group=<optimized out>, 
    loc=0x7ffff7a0f560 <_nl_global_locale>) at ../stdlib/strtol_l.c:292
292 ../stdlib/strtol_l.c: no such file or directory. 

I have no idea what this means :(.

EDIT 2: Ok, the error was indeed from the xml, here it is :

<ddg name="The frozen cave">
        <date>
                <day>01</day>
                <month>09</month>
                <year>2019</year>
        </date>
        <dmname>Pierre</dmname>
        <players>
                <player name="Camille">
                        <ac>5</ac>
                        <class>Thief</class>
                        <cname>Camigolas</cname>
                        <hp>4</hp>
                        <money>
                                <cp>10</cp>
                                <gp>10</gp>
                                <sp>10</sp>
                        </money>
                </player>
                <player name="Jean">
                        <ac>4</ac>
                        <class>Fighter</class>
                        <cname>Jeragorn</cname>
                        <hp>8</hp>
                        <money>
                                <cp>3</cp>
                                <gp>1</gp>
                                <sp>2</sp>
                        </money>
                </player>
                <player name="Paul">
                        <ac>5</ac>
                        <class>Cleric</class>
                        <cname>Paumli</cname>
                        <hp>6</hp>
                        <money>
                                <cp>9</cp>
                                <gp>5</gp>
                                <sp>9</sp>
                        </money>
                </player>
        </players>
</ddg>

I've tried several things and ended up discovering that the xmlChildrenNode of player is text.
I guess i just need to loop until i find the element i want but does anyone knows why it returns text ? (i just printf cur->name to discover that).
Thank you all for you answers :)!

Upvotes: 0

Views: 724

Answers (2)

Jason Viers
Jason Viers

Reputation: 1762

I've tried several things and ended up discovering that the xmlChildrenNode of player is text. I guess i just need to loop until i find the element i want but does anyone knows why it returns text

All whitespace between elements in XML files is significant. The <Player> node will have 11 node children:

  • a text node, the linebreak immediately after <Player> and spaces before <ac>
  • an element node, which is <ac> (which will have a text node child, the ac value)
  • a text node, the linebreak after </ac> and spaces before <class>
  • an element node, which is <class>
  • etc....

So that first "text" child you're seeing under <Player> is the newline and spaces that occur before <ac>.

You may want to pass XML_PARSE_NOBLANKS into xmlParseFile, which tells the parser to skip over "in-between" whitespace like this. Then <Player> will have the <ac> child, then the <class> child, etc. without the text nodes between.

Upvotes: 1

HAL9000
HAL9000

Reputation: 2188

nptr=0x0 probably means that strtol (or more presisely the function that was called by strtol) was called with the parameter nptr set to 0x0. The parameters nptr was most like expected to point to a valid string, but didn't.

What that likely means, is that xmlNodeListGetString() returns zero or NULL, depending on how you prefer to call the value.

When parsing external files, you should ALWAYS do error checking of the file content.

I would guess that cur->xmlChildrenNode doesn't have the value you expect it to, but it is hard to say without more info.

And by the way, c is one of those languages that has zero based arrays, so you should have int i = 0. (One based arrays are evil.) Do not be a heretic by simulating one-based arrays by having a dummy-element at players[0].

Upvotes: 1

Related Questions