1

I am not C programmer but have recently taking interest in it. I am trying to modify a node of a YAML file using the C libyaml library. When I try to modify the node from an event scalar data the compiler doesn't complain but I get segmentation fault errors.

while (!done)
{
    /* Get the next token. */

    if (!yaml_parser_parse(&parser, &event))
        goto parser_error;

    //yaml_parser_scan(&parser, &token);

    /* Check if this is the stream end. */

    if(beginServerNodes && event.type == 8) {
      beginServerNodes = 0;
    }

    if (event.type == YAML_SCALAR_EVENT) {
      if(beginServerNodes == 1) {
        //I WANT TO MODIFY THIS VALUE
        printf("%s\n", event.data.scalar.value);
      }
      if(strcmp("servers",event.data.scalar.value) == 0) {
        beginServerNodes = 1;
      }
    }

    if (event.type == YAML_STREAM_END_EVENT) {
        done = 1;
    }
    /* Emit the token. */

    if (!yaml_emitter_emit(&emitter, &event))
        goto emitter_error;
}

So while in that loop when I attempt to modify the following value

event.data.scalar.value

It must be of type yaml_char_t

  yaml_char_t *newHost = "10.132.16.48:6379:1 redis-001";
  event.data.scalar.value = newHost;
  event.data.scalar.length = sizeof(newHost);

The compiler doesn't complain and the code run by dies with segementation fault. If have seen the examples in the libyaml test directories but nothing is intuitive as far as simply editing a node, at least not to a C newb like myself.

Joseph Persico
  • 602
  • 7
  • 20
  • OK, one remark I can make without looking into the actual question: using `goto` is frowned upon by most programmers, and certainly not something you should be using when just starting out with C. It has some [ligitimate use cases](http://stackoverflow.com/questions/245742/examples-of-good-gotos-in-c-or-c), but when learning C it is best to stay away from it, instead of making it part of your normal everyday design workflow. – Rody Oldenhuis Jan 04 '17 at 11:56
  • It's not that `goto` is so difficult to use, but using it like any other flow control statement **will** lead to some extremely hard to find bugs, which take away most of your time and most of the fun of learning C. Read [this classic](http://homepages.cwi.nl/~storm/teaching/reader/Dijkstra68.pdf) by E.Dijkstra. – Rody Oldenhuis Jan 04 '17 at 11:58
  • @RodyOldenhuis I would agree with you there the use of that goto construct was taken directly from an example in the library itself. – Joseph Persico Jan 04 '17 at 11:58
  • Hmm...OK, strange. Well, just be warned then! :) – Rody Oldenhuis Jan 04 '17 at 12:00
  • 1
    I guess that you need to `strdup()` the data for newHost, and the length is to be calculated via `strlen()` – Rudi Jan 04 '17 at 12:33
  • @Rudi That actually resolved the segmentation fault issue! However I think the way I am going about modifying this node is a bad practice. Thanks for that reccomendation nonethless, feel free to post an answer so I can accept it as the solution, thanks. – Joseph Persico Jan 04 '17 at 12:43

1 Answers1

1

Libyaml expect that the values of each scalar can be removed via free(). So you need to initialize this value with malloc()ed memory:

const char* newHost = "10.132.16.48:6379:1 redis-001";
event.data.scalar.value = (yaml_char_t*)strdup(newHost);
event.data.scalar.length = strlen(newHost);
Rudi
  • 19,366
  • 3
  • 55
  • 77