Cocos2d-x: Crash when initiating TMXTiledMap from string - cocos2d-iphone

I'm having problems creating a tmx map from string input.
bool LevelManager::initLevel(int currentLevel)
{
const char* map;
try {
map = LevelManager::getLevel(currentLevel);
} catch (int) {
throw 1;
}
if(map != NULL){
CCLog("%s", map);
tileMap = CCTMXTiledMap::create(map);
tileMap->setAnchorPoint(ccp(0,0));
tileMap->setPosition(ccp(15,20));
this->addChild(tileMap, 5);
backgoundLayer = tileMap->layerNamed("Background");
} else {
throw 1;
}
return true;
}
Thats my code.
It is very unstable. Most of the times it crashes and sometimes it doesn't.
I'm loading my map from the string map. Wich is a const *char.
My map is named Level1.tmx and when i load the map like this: tileMap = CCTMXTiledMap::create("Level1.tmx"); it always works and never crashes.
And i know for a fact that the value of map is Level1.tmx because i log it in the line before the load.
When it crashes the log outputs this: (lldb)
and on the line tileMap->setAnchorPoint(ccp(0,0)); it says "Thread 1: EXC_BAD_ACCESS (code=2, adress=0x0)
Does anyone know why this happens and how to fix it?
Many thanks.
Ps: i'm using xcode, the latest cocos2d-x release and the iPhone simulator
Edit:
Using breakpoints i checked where things go bad while loading the tilemap.
on the line tileMap = CCTMXTiledMap::create(map);
my variable map is still fine
but on line tileMap->setAnchorPoint(ccp(0,0));
it is suddenly corrupted (most of the time)

It sounds like you're returning a char* string created on the stack, which means the memory may or may not be corrupted, depending on circumstances, moon phases, and what not.
So the question is: How is getLevel defined and what does it do (post the code)?
If you do something like this:
const char* LevelManager::getLevel(int level)
{
char* levelName = "default.tmx";
return levelName;
}
…then that's going to be the culprit. The levelName variable is created on the stack, no memory (on the heap) is allocated for it. The levelName variable and the memory it points to become invalid as soon as the method returns.
Hence when the method leaves this area of memory where levelName points to can be allocated by other parts of the program or other method's stack memory. Whatever is in that area of memory may still be the string, or it may be (partially) overridden by other bits and bytes.
PS: Your exception handling code is …. well it shows a lack of understanding what exception handling does, how to use it and especially when. I hope these are just remnants of trying to get to the bottom of the issue, otherwise get rid of it. I recommend reading a tutorial and introductions on C++ exception handling if you want to continue to use exceptions. Especially something like (map != NULL) should be an assertion, not an exception.

I fixed it.
const char* was to blame.
When returning my map as a char * it worked flawless.
const char *levelFileName = level.attribute("file").value();
char *levelChar = new char[strlen(levelFileName) + 1];
std:: strcpy (levelChar, levelFileName);
return levelChar;
Thats how i now return the map.

Related

RapidXML accessing sibling nodes causes segfaults for seemingly no reason

So I recently got a hold of RapidXML to use as a way to parse XML in my program, I have mainly been using it as a way to mess around but I have been getting some very weird issues that I'm really struggling to track down. Try and stick with me through this, because I was pretty thorough with trying to fix this issue, but I must be missing something.
First off here's the 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>
The function the segfault occurs:
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 happens on the second loop of the for loop to go through all the nodes, and triggers when it tries to do the imgName assignment. Here's where things get a bit odd. When doing a debug of the program, the initial child nodes breakdown shows it has memory pointers to the next nodes and it's elements/attributes etc. When investigating those nodes, you can see that the values exist and rapidxml has seemingly successfully parsed the file.
However, when the second loop occurs, child is shown to still have the exact same memory pointers, but this time the breakdown in values show they are essentially NULL values, so the program fails and we get the code 139. If you try and look at the previous node, that we have just come from the values are also NULL.
Now say, I comment out the line that calls on the AddTexture function, the node is able to print out all the nodes values no problems at all. (The Log method is essentially just printing to console until I do some more funky stuff with it.) so the problem must lie in the function? Here it is:
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!");
}*/
}
}
Ignoring the fact that strings are passed through and so should not affect the nodes in any way, this function is still a bit iffy. If I comment out everything it can work, but sometimes just crashes out again. Some of the code got commented out because instead of directly adding the key name, plus a memory pointer to a texture, I switched to storing the key and path strings, then I could just load the texture in memory later on as a workaround. This solution worked for a little bit, but sure enough began to segfault all over again.
I can't really reliably replicate or narrow down what causes the issue everytime, so would appreciate any help. Is RapidXML doc somehow going out of scope or something and being deleted?
For the record the class is practically just static along with the map that stores the texture pointers.
Thanks!
So for anybody coming back again in the future here's what was happening.
Yes, it was a scope issue but not for the xml_document as I kept initially thinking. The xml_file variable that was in the resources load function was going out of scope, which meant due to the way RapidXML stores things in memory, as soon as that goes out of scope then it frees up the memory, which led to the next time dynamic allocation happened by a specific function it would screw up the xml document and fill it with garbage data.
So I guess the best idea is to make sure xml_file and xml_document do not go out of scope. I have added some of the suggestions from previous answers, but I will point out those items WERE in the code, before being removed to help with the debug process.
Thanks everybody for the help/advice.
I'm not sure, but I think that Martin Honnen made the point.
If next_sibling() return the pointer to the text node between the two "image" elements, when you write
imgName = child->first_attribute("key")->value();
you obtain that child->first_attribute("key") is a null pointer, so the ->value() is dereferencing a null pointer. Crash!
I suppose you should get the next_sibling("image") element; something like
for (rapidxml::xml_node<>* child = resourcesNode->first_node("image");
child;
child = child->next_sibling("image"))
And to be sure not to use a null pointer, I strongly suggest you to check the attribute pointers (are you really sure that "image" elements ever carry the "key" and the "path" elements?); something like this
if ( child->first_attribute("key") )
imgName = child->first_attribute("key")->value();
else
; // do something
if ( child->first_attribute("path") )
imgPath = child->first_attribute("path")->value();
else
; // do something
p.s.: sorry for my bad English.
This line is setting my teeth on edge...
rapidxml::xml_document<>* resource = Resources::LoadResource(pathToFile);
LoadResource returns a pointer, but you never free it anywhere...?
Are you 100% sure that function isn't returning a pointer to an object that's now gone out of scope. Like this classic bug...
int * buggy()
{
int i= 42;
return &i; // UB
}
As #max66 says. You should use next_sibling("image"). If that's failing, you need to find out why.

Errors with initialization of an unordered_map inside of a class

The error I'm getting is Exception thrown at 0x00007FF77339C476 in VirusSimulator.exe: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF.
I've gone through my code with Visual Studio's debugger, and it seems like the error is from an attempt to call .size() on a unordered map of class objects.
Specifically, in the implementation of "list":
size_type size() const _NOEXCEPT
{ // return length of sequence
return (this->_Mysize());
}
When stepping through with the debugger and keeping an eye on local variables, I see: this 0xccccccccccccce0c folders={ size=??? }
(folders being the map of class variables)
Just below is a section of int main() where I manually initialize a default folder in each computer's drive's map of folders:
vector<Computer> macs;
for (int i = 0; i < mac_amount; i++)
{
macs.push_back(Computer(OSX)); //Initialize a computer with an operating system
}
for (int i = 0; i < macs.size(); i++)
{
//... Here is some code initializing connections between the computer objects
//and here is the manual insert of folders into the map
macs[i].getDrive()->addFolder("default"); //This used to be in the computers constructor but I moved it out here for testing
}
definition of addFolder:
void Harddrive::addFolder(string name)
{
Folder new_folder;
new_folder.set_name(name);
folders.insert(std::pair<string, Folder>(name, new_folder));
}
Basically, a random computer object then runs a virus that attempts to install itself to every other connected computer object by accessing the list of connections that is has, which contain pointers to the other computer objects.
It then de-references these and attempts to find the default folder on each respective computer's harddrive, but then fails to do so, claiming that the folder is uninitialized?
If any other pieces of my code are needed, then the full code can be found at https://github.com/BananaSky/VirusSimulator/tree/UnstableNetworkAdditions
Most of the code I've already tested for bugs, and that's why I've only posted such a small portion.
Any help is much appreciated!! (But also, it's getting late here and I might be going to sleep soon, so I apologize if I can't respond right away)
--ALSO: Please note that this is just a simulation and that I'm not actually intending to create any form of computer virus.
Here is the section of code where the error occurs (inside Virus.cpp):
vector<int> vulnerableConnectionIPs = installedOn->getNetworkAdapter()->getConnection()->getConnections();
for (int i = 0; i < vulnerableConnectionIPs.size(); i++)
{
Computer* accessRequest = installedOn->getNetworkAdapter()->getConnection()->getConnect(vulnerableConnectionIPs[i])->giveAccess();
if (accessRequest != NULL && accessRequest != installedOn)
{
if (accessRequest->getDrive()->getFolders()) //Error occurs here
{
accessRequest->Install(this, "default"); //Infect if infectable :)
}
else
{
cout << "No folders exist on " << accessRequest->getDrive()->getModel() << endl;
}
}
}
I'm working on replicating this on a smaller scale, and I'll probably get that posted by tomorrow
A memory address of 0xcccccccccccccccc (64-bit) or 0xcccccccc (32-bit) is Visual Studio's way of denoting an uninitialized block of memory. There's also 0xfeeefeee for already free'd and 0x00000000 for a null pointer.
Check that you have actually stored a value in the variable you are trying to access.
The values actually shown from error dialogs may be offset to values close to the above locations, you'll just have to trace through the program.
Your initial description of the error also points to at least trying to de-reference a null pointer.
More code would be helpful.

How could this address access violation?

Currently, there is one exception thrown from program written by C++, and running under windows.
here is the min dump information in the logs.
08/12/15 04:37:19 I New Information for UID 2d936a, FloorLoc F1505
08/12/15 04:37:19 E >>>>> EXCEPTION: Access Violation while trying to read address 20203567
[Fault address: 004AF945 01:000AE945 C:\Program Files (x86)\MySystems\WPR.exe 00400000] <<<<<
Call stack:
Load addr Address Frame Logical addr Module
00400000 004AF945 0588F8CC 0001:000AE945 C:\Program Files (x86)\MySystems\WPR.exe
00400000 004A89A4 0588FAEC 0001:000A79A4 C:\Program Files (x86)\MySystems\WPR.exe
According to the logical addr and .map file, I can find the codes where this exception thrown.
if (TempMSE->m_elem == NULL)
{
TempMSE->m_elem = new Element(element);
TempMSE->m_elem->SetLocation(FloorLoc);
LoggerInfo("New Information for UID %x, FloorLoc %s", Id, FloorLoc.ToString(buf));
}
TempMSE->m_elem->SetValue0(CIN_0, 0); // this exception is thrown here!!! through logical address 0001:000AE945
It seems that the m_elem gets one address from new operator, and there is NO exception for SetLocation function calling. Also the following log output correctly.
Why there is one exception thrown from SetValue0? Here is function SetValue0
void SetValue0(INDEX idx, DWORD val)
{
if (idx >= 0 && idx < MAX_INDEX){
if(val != m_Info[idx])
{
m_Info[idx] = val;
}
}
}
The m_Info is one array variable in the Element, and its size is MAX_INDEX.
On the other side, the address 0x20203567 seems one readable address, how could it be read violation?
Edit
Add more information here
class Element {
// other function here...
private:
FloorLocation m_FloorLoc;
DWORD m_Info[MAX_INDEX];
bool m_Dirty;
};
Element::Element(const Element& elem) {
m_FloorLoc = elem.m_FloorLoc;
for (int i = 0; i < MAX_INDEX; ++i)
m_Info[i] = elem.m_Info[i];
m_Dirty = elem.m_Dirty;
}
class FloorLocation {
// other function here...
private:
FloorId m_floorloc;
};
FloorLocation::FloorLocation( const FloorLocation& loc )
{
memset(&m_floorloc, ' ', 8); // space filled
if(loc.m_floorloc.id[0] != 0)
{
memcpy(m_floorloc.id, loc.m_floorloc.id, 8);
// eliminate nulls
for(int ndx=0; ndx < 8; ndx++)
{
if(m_floorloc.id[ndx] == 0)
m_floorloc.id[ndx]=' ';
}
}
}
typedef struct {
char id[8];
} FloorId;
These kinds of questions are a little hard to answer. I gave some ideas in comments, which I'll elaborate on here. Here are the kinds of things I look for when I have these sorts of crash logs with no other leads.
An access violation on read at that location suggests one of the following:
TempMSE is not a valid pointer, and the exception is thrown when attempting to get m_elem from it;
TempMSE->m_elem is not valid, and the exception is thrown inside SetValue0 when attempting to test the value of m_Info[idx].
In the latter case, this could occur if you delete TempMSE->m_elem somewhere but don't set it to NULL. If another thread is responsible for that delete, perhaps you have a race condition here where it's about to be set to NULL, but this code is executed first.
Another possibility is that either TempMSE or TempMSE->m_elem get corrupted somewhere along the way. This could be the result of a buffer overrun inside TempMSE (if you have arrays), or basically any sort of undefined behaviour that occurs near these pointers in memory. If TempMSE is on the stack, then look for any potential trouble there.
I don't want to fill this answer with other kinds of speculation (like heap corruption), but hopefully it gives you some avenues to try. The basic list of common culprits is this:
coding error (not initialising or resetting a value)
threading issues, race conditions...
undefined behaviour or overruns trashing data
Good luck!
I can't say what is actually wrong, but I would disassemble the code at 0x004AF945 - and several instructions before, and try to understand what part of the failing function that is.
As pointed out in one of the comments, the address that the fault happens at is suspiciously looking like 'C# ', which makes me think that somewhere a string is overflowing somewhere...
This is just a guess, but I suspect TempMSE->m_elem is what contains the value 0x20203567, and thus is NOT NULL when it tries to access it, meaning no logging is performed. [Obviously this is based on what code you have shown so far, and if there is logging before/after that show this is not the case, my second guess is that m_info is somehow wrong...

seg fault after end of function (C++)

I'm having a seg fault: 11 when I run a particular program. I feel like this problem wasn't present before I upgraded my system to Mac OS X 10.9, but it's possible I just overlooked it..
Anyway, my function looks like:
// this applies a warp to the field given, and saves output. simple!
void Apply(string warpName, string fieldName, bool conserve, string outName) {
// get lon, lat dimensions of warp
int noLongs = GetDimension(warpName, 3, "warp");
int noLats = GetDimension(warpName, 2, "warp");
int origNoLongs = noLongs, origNoLats = noLats;
// read in params
vector<double> params = ImportWarpFromNetCDF(warpName);
// rescale field to warp's dimensions, and read in
string tempName = "scaledField";
ReScale(fieldName, tempName, noLongs, noLats);
vector<vector<vector<double> > >inIntensities = ImportFieldFromNetCDF(tempName);
RemoveFile(tempName);
// just enter inIntensities for ref image, and 1 for lambda, to keep objective function happy
ObjectiveFunction objective(inIntensities, inIntensities, conserve, 1, false);
objective.setParameters(params);
// output files
ExportOutputToNetCDF(objective, outName);
cout << "BAH?!" << endl;
}
where the cout line at the end was just checking to see I'd got to the end of the function properly (which I have). Any thoughts on why this would be segfaulting here? I appreciate it might be hard to tell without seeing what the individual function calls do, and so I'll add those if necessary.
It doesn't actually matter too much, as this function is the last thing to be called (so the seg fault doesn't interrupt anything), but I still would rather get to the bottom of it!
The only thing that happens "after" the function are destructor calls. Check all your destructors of local variables. It looks like ObjectiveFunction is the only local variable that's not a primitive or standard library container, so check ObjectiveFunction::~ObjectiveFunction() for potential problems.

Pointer object in C++

I have a very simple class that looks as follows:
class CHeader
{
public:
CHeader();
~CHeader();
void SetCommand( const unsigned char cmd );
void SetFlag( const unsigned char flag );
public:
unsigned char iHeader[32];
};
void CHeader::SetCommand( const unsigned char cmd )
{
iHeader[0] = cmd;
}
void CHeader::SetFlag( const unsigned char flag )
{
iHeader[1] = flag;
}
Then, I have a method which takes a pointer to CHeader as input and looks
as follows:
void updateHeader(CHeader *Hdr)
{
unsigned char cmd = 'A';
unsigned char flag = 'B';
Hdr->SetCommand(cmd);
Hdr->SetFlag(flag);
...
}
Basically, this method simply sets some array values to a certain value.
Afterwards, I create then a pointer to an object of class CHeader and pass it to
the updateHeader function:
CHeader* hdr = new CHeader();
updateHeader(hdr);
In doing this, the program crashes as soon as it executes the Hdr->SetCommand(cmd)
line. Anyone sees the problem, any input would be really appreciated
When you run into a crash, act like a crime investigator: investigate the crime scene.
what is the information you get from your environment (access violation? any debug messages? what does the memory at *Hdr look like? ...)
Is the passed-in Hdr pointer valid?
Then use logical deduction, e.g.:
the dereferencing of Hdr causes an access violation
=> passed in Hdr points to invalid memory
=> either memory wasn't valid to start with (wrong pointer passed in), or memory was invalidated (object was deleted before passing in the pointer, or someone painted over the memory)
...
It's probably SEGFAULTing. Check the pointers.
After
your adding some source code
your comment that the thing runs on another machine
the fact that you use the term 'flag' and 'cmd' and some very small datatypes
making me assume the target machine is quite limited in capacity, I suggest testing the result of the new CHeader for validity: if the system runs out of resources, the resulting pointer will not refer to valid memory.
There is nothing wrong with the code you've provided.
Are you sure the pointer you've created is the same same address once you enter the 'updateHeader' function? Just to be sure, after new() note the address, fill the memory, sizeof(CHeader), with something you know is unique like 0XDEAD, then trace into the updateHeader function, making sure everything is equal.
Other than that, I wonder if it is an alignment issues. I know you're using 8 bit values, but try changing your array to unsigned ints or longs and see if you get the same issue. What architecture are you running this on?
Your code looks fine. The only potential issue I can see is that you have declared a CHeader constructor and destructor in your class, but do not show the implementation of either. I guess you have just omitted to show these, else the linker should have complained (if I duplicate this project in VC++6 it comes up with an 'unresolved external' error for the constructor. It should also have shown the same error for the destructor if you had a... delete hdr; ...statement in your code).
But it is actually not necessary to have an implementation for every method declared in a class unless the methods are actually going to get called (any unimplemented methods are simply ignored by the compiler/linker if never called). Of course, in the case of an object one of the constructor(s) has to be called when the object is instantiated - which is the reason the compiler will create a default constructor for you if you omit to add any constructors to your class. But it will be a serious error for your compiler to compile/link the above code without the implementation of your declared constructor, so I will really be surprised if this is the reason for your problem.
But the symptoms you describe definitely sounds like the 'hdr' pointer you are passing to the updateHeader function is invalid. The reason being that the 1st time you are dereferencing this pointer after the updateHeader function call is in the... Hdr->SetCommand(cmd); ...call (which you say crashes).
I can only think of 2 possible scenarios for this invalid pointer:
a.) You have some problem with your heap and the allocation of memory with the 'new' operator failed on creation of the 'hdr' object. Maybe you have insufficient heap space. On some embedded environments you may also need to provide 'custom' versions of the 'new' and 'delete' operator. The easiest way to check this (and you should always do) is to check the validity of the pointer after the allocation:
CHeader* hdr = new CHeader();
if(hdr) {
updateHeader(hdr);
}
else
//handle or throw exception...
The normal behaviour when 'new' fails should actually be to throw an exception - so the following code will cater for that as well:
try{
CHeader* hdr = new CHeader();
} catch(...) {
//handle or throw specific exception i.e. AfxThrowMemoryException() for MFC
}
if(hdr) {
updateHeader(hdr);
}
else
//handle or throw exception...
}
b.) You are using some older (possibly 16 bit and/or embedded) environment, where you may need to use a FAR pointer (which includes the SEGMENT address) for objects created on the heap.
I suspect that you will need to provide more details of your environment plus compiler to get any useful feedback on this problem.