Also habe ich RapidXML vor kurzem als eine Möglichkeit benutzt, um XML in meinem Programm zu parsen, ich habe es hauptsächlich als Möglichkeit benutzt, herumzualbern, aber ich habe es bekommen einige sehr seltsame Probleme, denen ich wirklich auf die Spur komme. Versuchen Sie, und bleiben Sie dabei, weil ich ziemlich gründlich versucht habe, dieses Problem zu beheben, aber ich muss etwas verpassen.RapidXML, der auf Geschwisterknoten zugreift, verursacht scheinbar keine Gründe für segfaults
Als erstes ist hier die XML:
<?xml version="1.0" encoding="utf-8" ?>
<resources>
<image key="tilemap_roguelikesheet" path="res/media/tilemaps/roguelikesheet.png" />
<image key="tilemap_tiles" path="res/media/tilemaps/tiles.png" />
</resources>
Die Funktion der segfault auftritt:
void TextureManager::LoadResource(const char* pathToFile)
{
rapidxml::xml_document<>* resource = Resources::LoadResource(pathToFile);
std::string imgName;
std::string imgPath;
if (resource != NULL)
{
rapidxml::xml_node<>* resourcesNode = resource->first_node("resources");
if (resourcesNode != NULL)
{
for (rapidxml::xml_node<>* child = resourcesNode->first_node("image"); child; child = child->next_sibling())
{
//Crash here on the second loop through.
imgName = child->first_attribute("key")->value();
imgPath = child->first_attribute("path")->value();
Astraeus::Log(moduleName, "Image Name: " + imgName);
Astraeus::Log(moduleName, "Image Path: " + imgPath);
TextureManager::AddTexture(imgName, imgPath);
}
}
else
{
Astraeus::Error(moduleName, "Resources node failed to load!");
}
resource->clear();
}
else
{
std::string fileName(pathToFile);
Astraeus::Error(moduleName, fileName + " could not be loaded.");
}
}
So segfault auf der zweiten Schleife der for-Schleife durch alle Knoten gehen geschieht und Trigger wenn es versucht, die Zuordnung imgName zu tun. Hier wird es etwas merkwürdig. Beim Debuggen des Programms zeigt der erste Kindknotenzusammenbruch, dass er Speicherzeiger auf die nächsten Knoten und seine Elemente/Attribute usw. hat. Wenn Sie diese Knoten untersuchen, können Sie sehen, dass die Werte existieren und rapidxml die Datei erfolgreich analysiert hat.
Wenn jedoch die zweite Schleife auftritt, zeigt Kind, noch genau die gleichen Speicherzeiger zu haben, aber dieses Mal zeigt die Aufschlüsselung in Werten, dass sie im Wesentlichen NULL-Werte sind, das Programm schlägt fehl und wir erhalten den Code 139. Wenn Sie versuchen, den vorherigen Knoten zu betrachten, den wir gerade von den Werten erhalten haben, sind auch NULL.
Jetzt sagen, ich kommentieren die Zeile, die die AddTexture-Funktion aufruft, der Knoten ist in der Lage, alle Knotenwerte überhaupt keine Probleme auszudrucken. (Die Log-Methode druckt im Wesentlichen nur auf die Konsole, bis ich ein paar mehr funky Sachen damit mache.) Also muss das Problem in der Funktion liegen? Hier ist sie:
void TextureManager::AddTexture(const std::string name, const std::string path)
{
Astraeus::Log(moduleName, "Loading texture: " + path);
if (texturesLookup.find(name) != texturesLookup.end())
{
Astraeus::Error(moduleName, "Texture Key: " + name + " already exists in map!");
}
else
{
texturesLookup.insert(std::make_pair(name, path));
//Texture* texture = new Texture();
/*if (texture->LoadFromFile(path))
{
//textures.insert(std::make_pair(name, texture));
}
else
{
Astraeus::Error(moduleName, "Failed to add texture " + name + " to TextureManager!");
}*/
}
}
Das Ignorieren der Tatsache, dass Zeichenketten durchlaufen werden, und so sollte nicht die Knoten in irgendeiner Weise beeinflussen, ist diese Funktion immer noch ein bisschen iffy ist. Wenn ich alles auskommentiere, kann es funktionieren, aber manchmal stürzt es einfach wieder ab. Ein Teil des Codes wurde auskommentiert, da ich den Schlüsselnamen und einen Speicherzeiger für eine Textur direkt hinzufügte, wechselte ich zum Speichern der Schlüssel- und Pfadzeichenfolgen und konnte die Textur später als Workaround in den Speicher laden. Diese Lösung funktionierte ein wenig, aber sie begann wieder zu segfault.
Ich kann nicht wirklich zuverlässig replizieren oder eingrenzen, was das Problem jedes Mal verursacht, so würde jede Hilfe zu schätzen wissen. Geht RapidXML doc irgendwie aus dem Geltungsbereich oder etwas und wird gelöscht?
Für den Datensatz ist die Klasse praktisch nur statisch zusammen mit der Karte, die die Texturzeiger speichert.
Danke!
Ich bin nicht vertraut mit dieser API, aber bedenken Sie, dass die nächsten Geschwister in den meisten XML-APIs, die ich kenne, alle Arten von Knoten und nicht nur Elementknoten zurückgeben können, so dass Sie wahrscheinlich den Textknoten zwischen den beiden Elementen treffen . –
RapidXML unterscheidet sich geringfügig in der Ausführung, da next_sibling() tatsächlich den nächsten richtigen Knoten (in diesem Fall) erhält, anstatt den Inhalt eines Knotens als seinen eigenen Textknoten zu behandeln. Wenn Sie den Text von diesen erhalten möchten, müssen Sie value() auf dem Knoten aufrufen (in meinem Code, der untergeordnet ist). Ich debuggte auch den Knotenwert, und so weiß ich, dass next_sibling() aufrufen wird und tatsächlich den nächsten richtigen Knoten sehen kann, außer wenn es alle Werte annulliert, bis zu dem Punkt, an dem der Zeiger zum vorherigen Knoten angezeigt wird Der Wert ist null. –
Ihre 'image' Elemente sind leer, aber es gibt nur Leerstellen zwischen den' image' Elementen. Funktioniert Ihr Code, wenn Sie z. ' '? –