Sign in to follow this  
Tallkotten

Pretty advanced pointer problem

Recommended Posts

Hello again Gamedev forum!

I'm back with a mind twister. I've sat with this for a few hours and haven't moved an inch forward. I am beaten.

The problem is with a pointer. I've "watched" it while debugging to follow it. And basically this is how it goes.

Object created, pointer is correct -> sends it around abit until finally arrived in Class "Content" -> pointer is correct -> Assign new pointer the same value -> Still correct -> Adjust some values in the object with help from pointer -> Goes back to gameLoop -> back into Content class -> update function running -> Program crashes

The reason why it crashes is because it tries to update the same values it changed earlier with the pointer stored in the class. The pointer has now changed from being a pointer to a Class to being a pointer to the Classes Interface which no real code in it.

And the annoying thing is that I've got 3 different classes that uses the same interface and the error only occurs with this newly created class, ergo I've must have screwed something up. But i can for the love of god not locate it.

I'm going to post the code to these steps now as well as upload the project in case someone wants to try to debug it on his/her own.

Object created, with the createGold function:
[CODE]
int gold = 20*level*(diff/2) + (rand() % 20*level*2 - 10*level);
if(gold > 0)
{
lootContVector.at(vectorsize-1)->moveToBag(createGold(x, y, gold));
}

Item* itemMngr::createGold(int x, int y, int amount)
{
Item* generateditem = NULL;
generateditem = new Currency(x, y, amount);
if(generateditem != NULL)
{
itemVector.push_back(generateditem);
}
return generateditem;
}
[/CODE]

Sends it forward to a newly created lootcontainer's function
[CODE]
bool LootContainer::moveToBag(Item* itemAdd)
{
bool itemMoved = false;
for(vector<Container*>::iterator it = containers.begin(); it != containers.end(); it++)
{
if(!itemMoved)
{
if(!(*it)->getFull())
{
(*it)->addItem(itemAdd);
itemMoved = true;
}
}
}
return itemMoved;
}
[/CODE]

Adds it to the content and changes some values
[CODE]
void Container::addItem(Item* itemAdd)
{
if(content != NULL)
{
removeItem();
}
if(itemAdd != NULL)
{
content = itemAdd;
content->setInCont(true);
content->setX(contBox.x);
content->setY(contBox.y);
full = true;
}
}
[/CODE]

Goes back to the gameloop which sends an update command that eventually reaches the Container class within lootcontainer
[CODE]
void Container::update()
{
if(content == NULL)
{
full = false;
}
else
{
content->setX(contBox.x);
content->setY(contBox.y);
}
}
[/CODE]

This code is where it crashes: "[color=#ff0000]content->setX(contBox.x);[/color]". If i comment that out it will instead crash on the render function. The reason is that the pointer is no longer (Currency*) but (class Item*) in the "watches window".

Another weird thing it that is does work sometimes, if you are quick enough to spawn the loot... but only once.

If you want to download this yourself you should know that it is my first project and probably has a lot of sloppy code in it. To make the error occur you must spawn a Chest by pressing "R" and open it up.

Greatly appreciates help [img]http://public.gamedev.net//public/style_emoticons/default/smile.png[/img]

EDIT: The attached file does not come with any DLL's... i am running all the SDL DLL's and by adding these files to the project folder you should be able to run it: https://www.dropbox.com/s/p8jz7na8yodojwc/0.0.0080.rar Edited by Tallkotten

Share this post


Link to post
Share on other sites
I do not have SDL and I'm using VS, gcc is a bit more ahead with C++11 features than VS, so I cannot compile your code, maybe you could also attach compiled debug build? VS should be able to attach and debug.

Other than that, does Container::content pointer change, or it's still the same? You don't seem to mention that (or I missed it).

Share this post


Link to post
Share on other sites
The C++ keyword 'break' lets you break out of the most recent loop, so this:
[CODE]
for(vector<Container*>::iterator it = containers.begin(); it != containers.end(); it++)
{
if(!itemMoved)
{
if(!(*it)->getFull())
{
(*it)->addItem(itemAdd);
itemMoved = true;
}
}
}
[/CODE]
...can be converted to:
[code]for(vector<Container*>::iterator it = containers.begin(); it != containers.end(); it++)
{
if(!(*it)->getFull())
{
(*it)->addItem(itemAdd);
break;
}
}[/code]

That's unrelated to your problem, though.
I expect the cause of your crash is here: [s](you have "if(content != NULL)" twice in a row)[/s] [color=#ff0000](oops, misread the code statements)[/color]
[code]void Container::addItem(Item* itemAdd)
{
//If 'content' (whatever that is!) is not NULL.
if(content != NULL)
{
removeItem(); //Maybe you invalidate the pointer here by mistake?
}
//You repeat the same condition statement... Did you mean "is null?". You probably want an 'else' here.
if(itemAdd != NULL)
{
content = itemAdd;
content->setInCont(true);
content->setX(contBox.x); //What is 'contBox'?
content->setY(contBox.y);
full = true;
}
}[/code] Edited by Servant of the Lord

Share this post


Link to post
Share on other sites
I'm pretty sure with any modern day compiler, your able to stop the execution of code at your desired lines. So start from the top of the stack,

I have a feeling your are slicing, you could try declare your setX and setY as virtual (in the inheritted classes) - or it could be possible that you've casted an object that doesn't even have the setX/setY

As you are calling a Pointer to Item, if you wish to have Polymorphic functionality you need to declare virtual on the desired functions eg

in weapon.cpp
[code]
void Weapon::setX(int x)
{
box.x = x;
}
[/code]

is now

[code]
virtual void Weapon::setX(int x)
{
box.x = x;
}
[/code]

I'm not sure what object Item* is supposed to represent, I've gone through your code briefly but I have not compiled it Edited by dimitri.adamou

Share this post


Link to post
Share on other sites
Well without debug symbols I can't really debug, also disassembly looks way too clean to be debug build. It crashes on nullptr error, looks like virtual function call. Do you ever use memcpy() or something similar, that could corrupt itemAdd somewhere before Container::Update()?

Edit:
After running several times I noticed it doesn't crash that often. Somehow I feel it might be heap corruption. Edited by Ripiz

Share this post


Link to post
Share on other sites
[s]FYI, I'll probably add more to this post in a little bit, so expect a few edits over the next hourish...[/s] Whoa, didn't realize it was such a big code dump and it was a Code::Blocks project. Nevermind, I'm not gonna wade through it.

[quote name='Tallkotten' timestamp='1344797036' post='4968788']
[CODE]
Item* itemMngr::createGold(int x, int y, int amount)
{
Item* generateditem = NULL;
generateditem = new Currency(x, y, amount);
if(generateditem != NULL)
{
itemVector.push_back(generateditem);
}
return generateditem;
}
[/CODE]
[/quote]
Don't do this. Not like that. [font=courier new,courier,monospace]new[/font] [b]will not[/b] return [font=courier new,courier,monospace]NULL[/font]. Ever*. It will throw an exception if it fails. Specifically, it will throw a [font=courier new,courier,monospace]std::bad_alloc[/font] exception. You should [s]probably[/s]definitely be using smart pointers too.
[size=2]*At least it won't ever return [font=courier new,courier,monospace]NULL[/font] when called like that. You have to explicitly use [url="http://www.cplusplus.com/reference/std/new/nothrow/"][font=courier new,courier,monospace]nothrow[/font][/url] if you want it to return [font=courier new,courier,monospace]NULL[/font] on an allocation failure instead of throw an exception.[/size] Edited by Cornstalks

Share this post


Link to post
Share on other sites
[quote name='Servant of the Lord' timestamp='1344803295' post='4968817']
The C++ keyword 'break' lets you break out of the most recent loop, so this:
[CODE]
for(vector<Container*>::iterator it = containers.begin(); it != containers.end(); it++)
{
if(!itemMoved)
{
if(!(*it)->getFull())
{
(*it)->addItem(itemAdd);
itemMoved = true;
}
}
}
[/CODE]
...can be converted to:
[code]for(vector<Container*>::iterator it = containers.begin(); it != containers.end(); it++)
{
if(!(*it)->getFull())
{
(*it)->addItem(itemAdd);
break;
}
}[/code]

That's unrelated to your problem, though.
[/quote]

Thank, will use that in the future! But the reasons i use the bool there is because other code need to check if that code succeeds or not ;)

[quote name='Servant of the Lord' timestamp='1344803295' post='4968817']
I expect the cause of your crash is here: [s](you have "if(content != NULL)" twice in a row)[/s] [color=#ff0000](oops, misread the code statements)[/color]
[code]void Container::addItem(Item* itemAdd)
{
//If 'content' (whatever that is!) is not NULL.
if(content != NULL)
{
removeItem(); //Maybe you invalidate the pointer here by mistake?
}
//You repeat the same condition statement... Did you mean "is null?". You probably want an 'else' here.
if(itemAdd != NULL)
{
content = itemAdd;
content->setInCont(true);
content->setX(contBox.x); //What is 'contBox'?
content->setY(contBox.y);
full = true;
}
}[/code]
[/quote]

Content is declared as "Item* content" and stores the pointer to the object which is locked in container (think of a bag slot in WOW or any other RPG).

removeitem sets the content variable to NULL, so i'm sure that not the problem. Actually i dont think the problem is in the Container class since both the class Weapon and Armor which got Item as an interface works fine.

contBox is the location and size of the container.

[quote name='dimitri.adamou' timestamp='1344803877' post='4968820']
I'm pretty sure with any modern day compiler, your able to stop the execution of code at your desired lines. So start from the top of the stack,

I have a feeling your are slicing, you could try declare your setX and setY as virtual (in the inheritted classes) - or it could be possible that you've casted an object that doesn't even have the setX/setY

As you are calling a Pointer to Item, if you wish to have Polymorphic functionality you need to declare virtual on the desired functions eg

in weapon.cpp
[code]
void Weapon::setX(int x)
{
box.x = x;
}
[/code]

is now

[code]
virtual void Weapon::setX(int x)
{
box.x = x;
}
[/code]

I'm not sure what object Item* is supposed to represent, I've gone through your code briefly but I have not compiled it
[/quote]

I actually doesn't really know how to debug roperly. I've learned myself to use Watches and Call-stack aswell as breakpoints. And as i said in my first post "This code is where it crashes: "content->setX(contBox.x);". If i comment that out it will instead crash on the render function. The reason is that the pointer is no longer (Currency*) but (class Item*) in the "watches window".".

Whilst googeling around on the problem i was having i say some post about slicing. I don't really know what it is thought. Might have to read into that.

Why would i make them virtual in the inheritted classes? What would that change, i only thought you made them virtual in interfaces.

Item* is an interface all the items will be using in the game. At the moment there are only "Weapon", "Armor" and the broken "Currency". this is my first project ever so i'm pretty sure i'll have to rewrite my code from the start at some point, even now i see how much worse i was at coding when i look at the little older code in my project.

[quote name='Ripiz' timestamp='1344804088' post='4968822']
Well without debug symbols I can't really debug, also disassembly looks way too clean to be debug build. It crashes on nullptr error, looks like virtual function call. Do you ever use memcpy() or something similar, that could corrupt itemAdd somewhere before Container::Update()?

Edit:
After running several times I noticed it doesn't crash that often. Somehow I feel it might be heap corruption.
[/quote]

I compiled it as debug, what did you mean i should do?

To your Edit:
Yeah, it doesn't but when you debug in CodeBlocks it crashes every time, but like you said, when you just run the code it doesn't crash all the time.

----

I think the problematic code lies within itemmngr.cpp in the randLoot func and createGold func. Or maybe in the Currency class itself. Because that is the only place i treat Currency any different from Weapon or Armor (also part of Item) and they work fine. Edited by Tallkotten

Share this post


Link to post
Share on other sites
[quote name='Cornstalks' timestamp='1344806082' post='4968830']
FYI, I'll probably add more to this post in a little bit, so expect a few edits over the next hourish...

[quote name='Tallkotten' timestamp='1344797036' post='4968788']
[CODE]
Item* itemMngr::createGold(int x, int y, int amount)
{
Item* generateditem = NULL;
generateditem = new Currency(x, y, amount);
if(generateditem != NULL)
{
itemVector.push_back(generateditem);
}
return generateditem;
}
[/CODE]
[/quote]
Don't do this. Not like that. [font=courier new,courier,monospace]new[/font] [b]will not[/b] return [font=courier new,courier,monospace]NULL[/font]. Ever*. It will throw an exception if it fails. Specifically, it will throw a [font=courier new,courier,monospace]std::bad_alloc[/font] exception.
[size=2]*At least it won't ever return [font=courier new,courier,monospace]NULL[/font] when called like that. You have to explicitly use [url="http://www.cplusplus.com/reference/std/new/nothrow/"][font=courier new,courier,monospace]nothrow[/font][/url] if you want it to return [font=courier new,courier,monospace]NULL[/font] on an allocation failure instead of throw an exception.[/size]
[/quote]

Yeah, result of tiredness and a code-paste of the code above thanks thought, will fix it!

Also, thank you very much for putting for much time into this. Really kind of you! Edited by Tallkotten

Share this post


Link to post
Share on other sites
Largely unrelated to your question but from the look of it in the event that moveToBag returns false then the Item pointer is just discarded and the object is not deleted. Really you should prefer to use smart pointers for this kind of thing, either std::shared_ptr (if your compiler supports it) or boost::shared_ptr are appropriate here. Chances are that better use of RAII containers would also help with the problem you're having now.

Afraid I've no other insight into why your code is crashing. When it does crash does the content pointer still have the same value (i.e. pointing to the same address) or has it been changed to something else or been nullified? If it is not the same value then clearly the problem is that the content pointer is being changed. If the the pointer is unmodified then the object has probably been prematurely deleted or corrupted somehow. I haven't looked at the full code but the problem might also be with accessing the x member of contBox, the full source code or crash details might trivially disprove that theory though :-) Edited by dmatter

Share this post


Link to post
Share on other sites
[quote name='dmatter' timestamp='1344807730' post='4968842']
Largely unrelated to your question but from the look of it in the event that moveToBag returns false then the Item pointer is just discarded and the object is not deleted. Really you should prefer to use smart pointers for this kind of thing, either std::shared_ptr (if your compiler supports it) or boost::shared_ptr are appropriate here. Chances are that better use of RAII containers would also help with the problem you're having now.

Afraid I've no other insight into why your code is crashing. When it does crash does the content pointer still have the same value (i.e. pointing to the same address) or has it been changed to something else or been nullified? If it is not the same value then clearly the problem is that the content pointer is being changed. If the the pointer is unmodified then the object has probably been prematurely deleted or corrupted somehow. I haven't looked at the full code but the problem might also be with accessing the x member of contBox, the full source code or crash details might trivially disprove that theory though :-)
[/quote]

You are correct, i'll have to fix that. Deleting the object seems like a sensible thing to do there. Thank you

The x member is clean. Atleast that what my compiler says. The pointer changes from "content = (Currency *)0x24e8f1a0" In the Additem function (in the container class) to "content = (class Item *)0x24e8f1a0" in the update function.

Probably the item getting corrupted or deleted somehow since the memory adress is the same. I've got "protection" in case it gets nullified so that shouldn't be the problem.

Share this post


Link to post
Share on other sites
I didn't locate the crash and didn't run the code because I didn't have SDL development libraries installed (only SDL2), but I have some general recommendations that might help. These are really quite general and you have probably of them, but I'll reiterate them anyway.

First of all, the class inheritance is a bit of a mess and memory seems to be leaking. The worst is that almost everything seems to derive from LoadFiles and its constructor loads all images, fonts etc. Each time anything derived from LoadFiles is created, and these classes seem to be many in number, all images and fonts probably get loaded again and again. I'm not 100% sure given that I've only taken a glance at the code, but it really seems to be so.

Secondly, there seems to be lot of inheritance. It is better to use composition in most cases. Try looking up composition vs inheritance. There was a good post about it on GameDev, but I can't find it at the moment.

There also seems to be a bit of duplicate code. For example Item::setDead(). Item could just as easily have boolean dead member and set it instead of it being marked abstract. All the child classes are just doing the same. Just try to find code that duplicates itself and remove it. It's a slow process at first and it's often easier to just copy-paste, but it will hurt a lot later even when trying to make sense of your own code that is months or years old. Also, the less code you have to read the more obvious the errors will become. I don't mean shortening the names of variables, but the logical duplicates where a new function could be used in more than one place or even when it makes logically more sense to keep it separately.

Now, the pointer-hell. There are a lot of pointers, so many I lost track. Whenever possible, try to use references, full memory copies and stack allocated variables. In my experience pointers are almost always bad unless you need to optimize something. And even then the pointers should be local.

There are also many references to pointers. A reference is technically a pointer anyway, with the restriction that it can not be reassigned to point to another location. For example instead of Cursor* &cursor it makes sense to use either Cursor* cursor or preferably Cursor& cursor since the pointer value is not reassigned and it would be a bad idea to do so anyway.

Then there is the problem with rendering code being mixed with the game state. Usually it is best to have the underlying structure separately and provide different views for it, but it's already way out of scope of what I planned to say at first and there's plenty said about it elsewhere.

I hope you get something out of my recommendations. Overall it's not bad for a first project at all. I wish I could be more thorough, but architecture and pointers are a huge subject and unfortunately without running the code seeking crash is like searching random uninitialized pointer from heap of bees.

Edit: Sorry as I am probably repeating much said above as I started writing when no other posts were made. I'm slow. Edited by mrjones

Share this post


Link to post
Share on other sites
[quote name='mrjones' timestamp='1344808483' post='4968851']
loads of helpful tips.
[/quote]

Thanks for the tips!

I will definitely looking up composition vs inheritance.

I've noticed my duplicate code as well. I've chosen to ignore it for the time being thought. Since much of the code is kind of a disaster i am stuck debating with myself if i should just rewrite it all and implement more support for stuff i want to to from the start or just try to clean up my code somewhere down the road.

So pointers and references can be used differently? I've always thought that a pointer of an variable returns it's memory position. A reference of that pointer returns the normal value. I didn't know i could use references by themselves, just thought i used them to kind of dissemble a pointer.

That i will definitely have to look into! Would you mind going further in depth about the advantages and differences between a pointer and reference? Would really appreciate it :)

If you don't mind i'd like to hear what you had to say about the rendering code. Since if i do decide to rewrite it all i'd hate to make the same mistakes again :)

Just to get someone else's opinion than my own, what would you have done? Clean up the code or just rewrite it? Since this is my first project it feels kind of "sad" to crap it and start all over, since it does take some time to get where i'm at with the code now.

Share this post


Link to post
Share on other sites
[quote name='Tallkotten' timestamp='1344808461' post='4968850']
Probably the item getting corrupted or deleted somehow since the memory adress is the same. I've got "protection" in case it gets nullified so that shouldn't be the problem.
[/quote]
If the object is deleted you should be able to tell by putting a breakpoint/logging in the destructor and/or anywhere that is likely to be doing the deleting. If the object is being corrupted then that's harder (the fault lies with probably unrelated code) but you could try to use your IDE to inspect the object at various points through the execution up to the crash and figure out when it becomes corrupted, it is then a matter of knowing what else was happening at that time (like a loop that writes off the end of an array).

Share this post


Link to post
Share on other sites
The thing is that the pointer isn't really being touched or anything after that last use and the call to update it's position. One second it's working. But as fast as it leaves that code behind it doesn't. Almost acts like a temporary variable, even though it's not

Share this post


Link to post
Share on other sites
[quote name='Cornstalks' timestamp='1344806082' post='4968830']
[s]FYI, I'll probably add more to this post in a little bit, so expect a few edits over the next hourish...[/s] Whoa, didn't realize it was such a big code dump and it was a Code::Blocks project. Nevermind, I'm not gonna wade through it.
[/quote]

Well the only relevant code is in a few functions. If you are still interested i can tell you which ones. I just posted the whole project if someone felt they wanted to debug it themselves.

Share this post


Link to post
Share on other sites
[quote]
So pointers and references can be used differently? I've always thought that a pointer of an variable returns it's memory position. A reference of that pointer returns the normal value. I didn't know i could use references by themselves, just thought i used them to kind of dissemble a pointer.
[/quote]

I'm going to try to give an explanation that I use for myself when coding and while it's not pure, it's easier to understand and it works. However, you'd do well to look up other sources that probably explain it better and more correctly than I do.

First the declaration of a different variables:
[code]
int value=0; // Integer value (takes up 32 bits on 32 bit system). Should be initialized almost always.
int* pointer=&value; // Pointer value (takes also up 32 bits on 32 bit system, but used differently). Should also be initialized almost always.
int& reference=value; // Reference must always be initialized! Compiler checks against it and won't let simple int& reference; pass
[/code]

The first is obvious, it reserves 32bits for the value. The pointer is also 32 bits and points to memory location of value. The reference acts pretty similarly to pointer. The main differences are that reference can not be reassigned. When assigning new value to it, it is assigned to value, not to itself. The only bad things that can happen with a reference is that value goes out of scope or is destroyed before the reference goes out of scope. With a pointer one can accidentally reassign its value and it will point to something that is no longer there.

About references to pointers.
[code]
int value=0;
int& referenceToValue=value; // References value
int* pointer=&value; // Pointer to value
int*& referenceToPointer=pointer; // References pointer, so it technically acts as pointer to pointer

// All these operations store 10 in value
value=10;
referenceToValue=10;
*pointer=10;
*referenceToPointer=10;
[/code]

There's a lot of material on the subject and it usually takes a while to wrap ones head around it, so just search for pointer vs reference.

[quote]
If you don't mind i'd like to hear what you had to say about the rendering code. Since if i do decide to rewrite it all i'd hate to make the same mistakes again
[/quote]

It's better to separate the base-logic and rendering code except in some borderline scenarios. This is a simple example on how I might set it up for a game similar to yours that has inventory and loot. And it doesn't have any explicit pointers at all:
[code]
#include <vector>

// The logical part
/** Item component is the baseclass for WeaponComponent and other possible components.
It exists, because enable/disable functionality is shared */
class ItemComponent {
private:
bool enabled; ///< For enabling/disabling component

public:
ItemComponent() : enabled(false) {}

void enable() { enabled=true; }
};

/** A weapon component is item component */
class WeaponComponent : public ItemComponent {
private:
double damage; ///< Damage that the weapon might cause

public:
/** Constructor with default being a weapon that does nothing */
WeaponComponent(double _damage=0.0) : damage(_damage) {}
};

/** It does not matter whether the item is in the world as a loot or in inventory. We won't put anything here that is world specific (eg position). */
class Item {
private:
WeaponComponent weapon; ///< Weapon component. Enable the component, if the item is a weapon.
// If memory consumption is a problem, Weapon* could be used instead, but then copy
// constructor and assignment operator must be overloaded to create copies of all components.
// At the moment it is not needed, because ItemComponent holds entire copy of weapon anyway.

public:
void enableWeaponComponent() { weapon.enable(); }///< For convenience

/** Get weapon component reference as constant reference */
const WeaponComponent& getWeaponComponent() const { return weapon; }

/** Set weapon component. An assigment is made and contents of passed const
reference to some other weapon are copied to weapon component of this item */
void setWeaponComponent(const WeaponComponent& _weapon) { weapon=_weapon; }
};

/** Provide separate loot item to give it world position */
class LootItem {
private:
int x, y;
Item item; // Easier to have the item here

public:
LootItem(int _x=0, int _y=0, Item _item=Item()) : x(_x), y(_y), item(_item) {}

const Item& getItem() const { return item; }
};

typedef std::vector< Item > Inventory; // Inventory now becomes a simple vector where we can put items and take them back out again. Also note that we are not keeping pointers, but entire items
typedef std::vector< LootItem > Loot; // Same with loot

// User-interface and rendering.
// I'm leaving out a lot from here, because the example has already grown beyond the complexity I intended.
/** Rendering and user interface handling. The reason why this is provided separately, is because there can be different views on inventory.
For example we might want to render inventory of enemies differently over the head of enemy and so on. */
class InventoryUserInterface {
public:
/** No need to hide rendering of items */
void renderItem(Item item) {
// Render item however you want
}

/** Render inventory */
void render(Inventory& inventory) {
for(Inventory::const_iterator item=inventory.begin(); item!=inventory.end(); ++item) {
// Render the item however you want. You might have components provide the information about which
// images to use or item itself or just render text about which components are enabled and which are not.
renderItem(*item);
}
}

// Omitted handling user events etc completely
};

// Setting up
int main() {
Loot loot;
Inventory inventory; // Create inventory

{ // We can for example place initial items to inventory inside this scope. As soon as
// the scope ends weaponToGoToInventory will be automagically gone, but its copies will remain in inventory
Item weaponToGoToInventory;
weaponToGoToInventory.enableWeaponComponent(); // Make the item into actual weapon
inventory.push_back(weaponToGoToInventory); // Push a weapon to inventory
inventory.push_back(weaponToGoToInventory);
// We can push more than one of the same weapon to inventory and it won't crash!
// A full copy will be made each time and since weaponToGoToInventory only exists in this scope, we can just forget about it
}

{
Item genericItem; // Create a generic item
LootItem lootItem(10, 25, genericItem); // Create loot item that is now positioned at (10, 25)
// and holds weapon as it's item
loot.push_back(lootItem); // Push it to loot
}

// Taking last item from loot and placing to inventory.
// A separate class that keeps track of both loot and inventory should normally provide a method for it
// that looks something like this: void lastFromLootToInventory();
Item item=loot.back().getItem(); // We take the item from LootItem
loot.pop_back();
inventory.push_back(item); // And we place it to inventory

InventoryUserInterface inventoryUserInterface; // Create userinterface for displaying inventor(y|ies)
inventoryUserInterface.render(inventory); // Render items in inventory

return 0;
}
[/code]

Also, don't scrap your code. Even if you decide to rewrite it, it is very useful to have the old code and you can still use large portions of it. Edited by mrjones

Share this post


Link to post
Share on other sites
I've downloaded Eclipse, went through 3 tutorials and it still couldn't compile Hello World. Piece of crap, not a tool.
Similar thing happened with Code::Blocks, but I removed it right away after it couldn't compile, I didn't bother.

Does it reach line [i]content = itemAdd;[/i] in [i]Container::addItem(Item* itemAdd)[/i]?

Share this post


Link to post
Share on other sites
[quote name='Ripiz' timestamp='1344847640' post='4968984']
I've downloaded Eclipse, went through 3 tutorials and it still couldn't compile Hello World. Piece of crap, not a tool.
Similar thing happened with Code::Blocks, but I removed it right away after it couldn't compile, I didn't bother.

Does it reach line [i]content = itemAdd;[/i] in [i]Container::addItem(Item* itemAdd)[/i]?
[/quote]

Yes, it's only after that that it crashes. Either when it tries to update "content" variable or when it tries to draw from it

Share this post


Link to post
Share on other sites
I'm sorry Servant of the Lord, I have to disagree strongly.

A "break;" statement in a for loop doesn't make sense. By doing this:
[CODE]
for(vector<Container*>::iterator it = containers.begin(); it != containers.end(); it++)
{
if(!(*it)->getFull())
{
(*it)->addItem(itemAdd);
break;
}
}
[/CODE]
You modified a for loop to a while loop. Hence what you really need here is a while loop.
Both works fine, it makes a difference when a Theoretical IT guy needs to verifiy the program.
A for loop is simple, it knows at runtime the exact amount of times the body is executed. A while loop is a bit more complicated. And by camouflaging a for loop in a while loop, you make the poor guy cry.


To the problem: it seems to me your problem lies in your OO class concept, or maybe a missing virtual keyword in a method. If you want to read up on the C++ virual keyword, [url="http://www.learncpp.com"]www.learncpp.com[/url] had a good tutorial on it IMO.
I'm sorry, I cannot debug the code from where I currently am. Edited by Bluefirehawk

Share this post


Link to post
Share on other sites
[quote name='Bluefirehawk' timestamp='1344849432' post='4968990']
I'm sorry Servant of the Lord, I have to disagree strongly.

A "break;" statement in a for loop doesn't make sense. By doing this:
[CODE]
for(vector<Container*>::iterator it = containers.begin(); it != containers.end(); it++)
{
if(!(*it)->getFull())
{
(*it)->addItem(itemAdd);
break;
}
}
[/CODE]
You modified a for loop to a while loop. Hence what you really need here is a while loop.
[/quote]
If you want to talk about semantics (and I totally agree about that), then it's not even a while loop you want. The semantics of the code is, in my opinion, "find the first non-full item and add to it if there is one"; thus, std::find_if() and an if-statement.

The semantics of a search in this case is std::find_if, not a while loop.

Share this post


Link to post
Share on other sites
[quote name='Tallkotten' timestamp='1344849022' post='4968988']
[quote name='Ripiz' timestamp='1344847640' post='4968984']
I've downloaded Eclipse, went through 3 tutorials and it still couldn't compile Hello World. Piece of crap, not a tool.
Similar thing happened with Code::Blocks, but I removed it right away after it couldn't compile, I didn't bother.

Does it reach line [i]content = itemAdd;[/i] in [i]Container::addItem(Item* itemAdd)[/i]?
[/quote]

Yes, it's only after that that it crashes. Either when it tries to update "content" variable or when it tries to draw from it
[/quote]

What debugger shows about itemAdd at that line? Is it still Currency type, or not anymore?
If it is, add pointer to watch list, then try to debug further to see when it changes.

Share this post


Link to post
Share on other sites
[quote name='Tallkotten' timestamp='1344806243' post='4968831']
[quote name='dimitri.adamou' timestamp='1344803877' post='4968820']
I'm pretty sure with any modern day compiler, your able to stop the execution of code at your desired lines. So start from the top of the stack,

I have a feeling your are slicing, you could try declare your setX and setY as virtual (in the inheritted classes) - or it could be possible that you've casted an object that doesn't even have the setX/setY

As you are calling a Pointer to Item, if you wish to have Polymorphic functionality you need to declare virtual on the desired functions eg

in weapon.cpp
[code]
void Weapon::setX(int x)
{
box.x = x;
}
[/code]

is now

[code]
virtual void Weapon::setX(int x)
{
box.x = x;
}
[/code]

I'm not sure what object Item* is supposed to represent, I've gone through your code briefly but I have not compiled it
[/quote]

I actually doesn't really know how to debug roperly. I've learned myself to use Watches and Call-stack aswell as breakpoints. And as i said in my first post "This code is where it crashes: "content->setX(contBox.x);". If i comment that out it will instead crash on the render function. The reason is that the pointer is no longer (Currency*) but (class Item*) in the "watches window".".

Whilst googeling around on the problem i was having i say some post about slicing. I don't really know what it is thought. Might have to read into that.

Why would i make them virtual in the inheritted classes? What would that change, i only thought you made them virtual in interfaces.

Item* is an interface all the items will be using in the game. At the moment there are only "Weapon", "Armor" and the broken "Currency". this is my first project ever so i'm pretty sure i'll have to rewrite my code from the start at some point, even now i see how much worse i was at coding when i look at the little older code in my project.
[/quote]

Oops. My bad, I went through your code and saw that in item.h virtual is defined.. but it is derived from yet another class.

Your classes are trying to do too much, the design is a bit confusing - you should try seperate everything as much as possible. Someone wrote a really good article on gdev.net, but I can't seem to find it.. it spoke about foward declaration and just maintaining neatness in code


As for slicing here is a simple quick example

[code]
class firstclass
{
public:
void hello() { cout << "firstclass::hello();" << endl; }
}

class secondclass : public firstclass
{
public:
int valA;
void hello() { cout << "secondclass::hello();" << endl; }
}


firstclass A;
secondclass B;

A = B; //slicing occurs. valA has no access
A.hello(); // firstclass::hello(); gets printed out
[/code]

Thats slicing at its bare-basics, but with pointers and virtual tables this can get resolved (after looking a bit deeper in your code that doesn't appear to be the problem)

I haven't spent much time in there though. But yeah, back to my original point - your classes are trying to do too much

Share this post


Link to post
Share on other sites
[quote name='mrjones' timestamp='1344847373' post='4968981']
[color=#00ff00]Text[/color]
Also, don't scrap your code. Even if you decide to rewrite it, it is very useful to have the old code and you can still use large portions of it.
[/quote]

Thank you! That helped alot. I'll have to look further into it thought.

Also i wont ever completely scrap the code in case i actually need something from it.

Share this post


Link to post
Share on other sites
[quote name='Ripiz' timestamp='1344852766' post='4969001']
[quote name='Tallkotten' timestamp='1344849022' post='4968988']
[quote name='Ripiz' timestamp='1344847640' post='4968984']
I've downloaded Eclipse, went through 3 tutorials and it still couldn't compile Hello World. Piece of crap, not a tool.
Similar thing happened with Code::Blocks, but I removed it right away after it couldn't compile, I didn't bother.

Does it reach line [i]content = itemAdd;[/i] in [i]Container::addItem(Item* itemAdd)[/i]?
[/quote]

Yes, it's only after that that it crashes. Either when it tries to update "content" variable or when it tries to draw from it
[/quote]

What debugger shows about itemAdd at that line? Is it still Currency type, or not anymore?
If it is, add pointer to watch list, then try to debug further to see when it changes.
[/quote]

It is of Currency type in the addItem func.

I've already done that but, i'll have to do it again i guess. Need to get this working

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this