-1

I am developing a game using cocos2d-x and C++, and I need to load a bunch of YAML files for this application. I tried using the yaml-cpp library with quite good results.

The problem is that this library seems to be very unstable (at least under cocos2d-x on iOS), since almost 20% of the time it fails loading the same YAML file throwing "end of map not found", "invalid map element", or errors like these ones.

I followed the HowToParseADocument guide, so I think I got it correct. But, since it's not 100% reliable, I am looking for something more stable. Eg:

long size = 0;
unsigned char *yaml = FileUtils::getInstance()->getFileData("file.yml", "r", &size);
std::stringstream is;
is << yaml;

YAML::Parser parser(is);
YAML::Node doc;
while(parser.GetNextDocument(doc)) {
  instance->settings = doc.Clone();
}

The parser usally breaks at the parser.GetNextDocument(doc) call. The document I am trying to read is plain YAML with key: value lists in this simple form:

# Comment
section1:
  param1: value1
  param2: value2

# Comment
section2:
  param1: value1
  param2: value2

Edit

I am not allowed to disclose the content of the original YAML file, but I can give you some information:

  1. It only contains maps, and not arrays, aliases or other particular constructs
  2. Those values are integers, float or strings
  3. It has been linted with this free tool, with success.

The code I used to read it, posted up there, it's always in that form, and I do not modify it to make the app run correctly. It's just that the app starts and works or starts and does not work. Since I am changing nothing in the middle, I really do not understand what's happening.

marzapower
  • 5,531
  • 7
  • 38
  • 76
  • How are you using the yaml parser right now? Perhaps you pass in an object by reference which becomes a dangling pointer and the parser ends up reading from overwritten memory. It's a possibility. – CodeSmile Nov 26 '13 at 09:40
  • I am using it as shown in the question (I extended the piece of code to include the source file opening). Nothing different from what show in the guide. At the first call of the parser, it breaks (not always). – marzapower Nov 26 '13 at 10:16
  • I imagine this might be a CR/LF type issue, or perhaps the text file is encoded as UTF16 or some other encoding not correctly handled by the YAML parser. Or mixing tabs and spaces. Just making guesses. – CodeSmile Nov 26 '13 at 10:20
  • The problem is not that I'm not capable of reading it. It reads correctly, but -sadly- 20% of the time the yaml-cpp library breaks. I mean, I launch the app and it's fine. Another time and still fine. A third time it breaks. And so on ... – marzapower Nov 26 '13 at 10:29
  • Can you post the *exact* YAML file and *exact* code you're using? If either the file or the code is too large, try to pare it down until you get something that you can post here. (If it stops breaking when you remove something, then post what happened here too, since that's a useful clue!) – Jesse Beder Nov 26 '13 at 14:12
  • The point is, it's a bit suspicious when you say "The document I am trying to read is... in this simple form." - is that the YAML file you're trying to read, or is it "like" the YAML file you're trying to read? – Jesse Beder Nov 26 '13 at 14:13
  • It is like, in the sense that it only contains maps, and not arrays or aliases. The code I use to read it is the complete one pasted in the question. I am not allowed to disclose the full YAML file, but it has been linted with this: http://yamllint.com/ – marzapower Nov 26 '13 at 14:22
  • I repeat. I use this same code, without modifications. Once in a while it breaks. With no reason, since nothing has been changed. – marzapower Nov 26 '13 at 14:23

1 Answers1

1

It's a bit hard to guess at the solution because you won't provide an actual example, but:

Who owns the data at the unsigned char* returned by getFileData? If that function itself owns the data, then it is no longer valid after the function returns, and so all sorts of crazy stuff might happen.

To validate what's happening here (beyond looking at the implementation of getFileData), you could print out is.string() before calling YAML::Parser parser(is); and see if that prints the expected YAML.

Jesse Beder
  • 33,081
  • 21
  • 109
  • 146
  • The `getFileData` function is defined here: https://github.com/cocos2d/cocos2d-x/blob/develop/cocos/2d/platform/CCFileUtils.cpp . That `unsigned char *` object lives only in that function, and is used only within the function, as shown. – marzapower Nov 26 '13 at 15:11
  • Ok, the `is.str()` output shows that currently two different files have been "merged" in that stream. The strange fact is that I am reading two different YAML files using different classes and static methods that just share the `FileUtils` call from the cocos2d-x framework. – marzapower Nov 26 '13 at 15:16
  • It seems a bug of cocos2d-x, but I cannot understand why that function is capable of merging two separate memory allocations. – marzapower Nov 26 '13 at 15:17
  • 1
    When you file the bug with cocos2d-x, can you post the link to the bug tracker here? That will help other people with the same problem. – Jesse Beder Nov 26 '13 at 16:26