I don't understand what is happening to my program...

I have a feeling that private members are marked private for a reason, because I'm having a serious error with accessing base-class data types via inheritance and declaring friends within classes...

If you run the test program after attaching the header in your include file you'll understand what I mean... the code is attached.

Sorry, I would actually post it but it's far too long and I have a feeling that the error may exist in more places since I used the friend modifier extensively =/

Note: I was trying to create a Game Creation library (well, namely for RPG's so I was going to rename it) by using a menu-type cluster object as well as "action" objects clustered together to be fired all at once, or select firing or both. Basically the purpose of the program is to allow flexibility for users to create their own games.

Edit: To be more clear, the information I'm trying to access isn't appearing on the screen properly or not at all.

Recommended Answers

All 13 Replies

After a quick look into it, I suggest that you get rid of malloc() usage. You are using 'delete' on memory that has been malloc'ed - that must not happen.
Then about 'delete', you only can delete something that has been allocated by 'new', consider

class a
{
public:
    a(){}

} instance; // an instance of class a

void somefunction(a* aptr)
{
    delete aptr;
}
int main()
{
    a * aptr = new a;

    somefunction(aptr);  // this is OK

    somefunction(&instance);    // <- must not happen

    return 0;
}

There were some other issues too, but I think first you could make sure that the basic memory operations are in order.
When I tried the program, addObject(adephi); causes the run-time to report damaged heap.

After a quick look into it, I suggest that you get rid of malloc() usage. You are using 'delete' on memory that has been malloc'ed - that must not happen.
Then about 'delete', you only can delete something that has been allocated by 'new', consider

class a
{
public:
    a(){}

} instance; // an instance of class a

void somefunction(a* aptr)
{
    delete aptr;
}
int main()
{
    a * aptr = new a;

    somefunction(aptr);  // this is OK

    somefunction(&instance);    // <- must not happen

    return 0;
}

There were some other issues too, but I think first you could make sure that the basic memory operations are in order.
When I tried the program, addObject(adephi); causes the run-time to report damaged heap.

Oh that's interesting. I was told to delete memory that was dynamically allocated and that malloc was one of the types that you could delete?

On a side note I'm using Dev-Cpp 4.9 and I haven't updated my compiler so I don't get those kind of warnings unfortunately.

Oh that's interesting. I was told to delete memory that was dynamically allocated and that malloc was one of the types that you could delete?

On a side note I'm using Dev-Cpp 4.9 and I haven't updated my compiler so I don't get those kind of warnings unfortunately.

Whenever you use malloc() then free the memory using free().
Whenever you use new, then free the memory using delete.

Whenever you use malloc() then free the memory using free().
Whenever you use new, then free the memory using delete.

Thank you very much for the clarification.

I made the changes. Here are the files with the revisions.

Thank you very much for the clarification.

I made the changes. Here are the files with the revisions.

Hmm, wouldn't it be better to drop usage of malloc()/free() since you are working with objects instead of raw native types i.e. consistently use new/delete. And maybe consider e.g. STL list for storing objects/object pointers, to save yourself the hassle of memory management.

Anyway, note that you must not issue free() on anything that has not been malloc'ed. That is just what is now happening in addObject(), that crashes the program at very early stages (before main() is called).

Hmm, wouldn't it be better to drop usage of malloc()/free() since you are working with objects instead of raw native types i.e. consistently use new/delete. And maybe consider e.g. STL list for storing objects/object pointers, to save yourself the hassle of memory management.

Anyway, note that you must not issue free() on anything that has not been malloc'ed. That is just what is now happening in addObject(), that crashes the program at very early stages (before main() is called).

Ah I see what's happening.

Because I didn't use new on my objects, their constructors never ran therefore the data was never initialized in the first place!

Wow I learned an incredible lesson here.

The reason why I used malloc instead of new was because I was looking for an alternative around allocating memory for temporary/abstract objects since they require an extension and override within the extensions.

Apparently I was trying to cheat the system and I get bit in the ass for doing so =/

I'll make the changes again. Thank you very much.

Honestly, my compiler is not giving me these warnings! What compiler should I update to in order to get these messages?

Honestly, my compiler is not giving me these warnings! What compiler should I update to in order to get these messages?

Those are not compiler warnings but instead run-time checks wrt heap usage. The compiler will not catch the errors that occur in the program, but the run-time checks will alert you on the spot. Try e.g. a VC ++ Express 2008.

It appears that you are not yet fully understanding about memory allocation/deallocation, so
if you use the malloc/free, every pointer you 'free' must have been malloc'ed, no exceptions.
if you use the new/delete, every pointer you 'delete' must have been new'ed, no exceptions.

I'm also trying to say that if you have a non-dynamic 'object', you must not issue free nor delete on a pointer to such object. This in mind, go through the code and see what happens with e.g. [B]bound[/B] ("Bound"), [B]adephi[/B] ("Adephi"); .

Those are not compiler warnings but instead run-time checks wrt heap usage. The compiler will not catch the errors that occur in the program, but the run-time checks will alert you on the spot. Try e.g. a VC ++ Express 2008.

It appears that you are not yet fully understanding about memory allocation/deallocation, so
if you use the malloc/free, every pointer you 'free' must have been malloc'ed, no exceptions.
if you use the new/delete, every pointer you 'delete' must have been new'ed, no exceptions.

I'm also trying to say that if you have a non-dynamic 'object', you must not issue free nor delete on a pointer to such object. This in mind, go through the code and see what happens with e.g. [B]bound[/B] ("Bound"), [B]adephi[/B] ("Adephi"); .

I think I understand a bit more now. I've revised the code again and this time I also dynamically allocated memory for char pointers I declared in class-scope.

Here are the revisions again, and this time it seems as if the program is working... but if there are still errors please point them out.

Edit: Oh actually there is one issue - I'm having trouble comparing a null-initialized char-array to a char pointer. What would you suggest?

Nevermind about the comparison, I created a class that does char pointer to char pointer comparisons.

My biggest problem now is the process of running the engine part's run overridden run method.

I have the revised files listed with the addition of the class I created to do the comparison.

Edit: Did some more revisions... found the error.

I was attempting to "free" memory from the previously allocated indice in the addObject portion of the code but I simply deleted the pointer gluing the other pointers together causing them to float freely, then allocated them to a temporary pointer then reallocated them to the regular double pointer... Hopefully I did this process correctly.

At the moment no information is lost and the virtual run method is overridden by the user's Engine Part run method which is exactly what I wanted. If there's still a problem with this please let me know.

Game_Object **tempPtr = new Game_Object*[amount];
                              
                           for(int i = 0; i < amount; i++){
                              tempPtr[i] = new Game_Object[1];     
                              tempPtr[i] = obj[i];
                           }
                           delete[] obj; //deletes the pointer pointing to the pointers, causing the pointers
                                         //to "float" freely in memory, but tempPtr holds a ref to them
                           
                           obj = new Game_Object*[amount];
                          
                           for(int i = 0; i < amount; i++){
                              obj[i] = new Game_Object[1];
                              obj[i] = tempPtr[i];
                              
                           } 
                          delete tempPtr;

Nevermind about the comparison, I created a class that does char pointer to char pointer comparisons.

// what will 'cmp' be ...
const int cmp = s_manip.compare("abc","abcd");

A diagnostics suggestion, add the following destructor

~Game_Object()
{
    std::cout << "~Game_Object(): " << objName << std::endl;
}

It will tell you that the memory management is not right.

You already have a Game_Object * in obj, you don't have to allocate and assign a new Game_Object ..

obj[i] = new Game_Object[1]; // you don't need this line
obj[i] = tempPtr[i];

Then strlen() returns the length of a string excluding the terminating NULL character but strcpy copies the string and appends the terminating NULL character <-> you have many one-byte-off memory allocations/assignments/overwrites there.

Then an example of a practice you effectively use

struct test
{
    int member_var;
    
    test() : member_var(0){}
    ~test(){}

    void f()
    {
        cout << member_var << endl;
    }

    static test & getObj()
    {
        test * p = 0;
        return *p;
    }
};

int main(int argc, char *argv[])
{
	test & obj = test::getObj();
	obj.f();

	return 0;
}

I wonder why are you not using std::string?

I still suggest to drop the manual allocation/reallocation schemes and use a STL container.

// what will 'cmp' be ...
const int cmp = s_manip.compare("abc","abcd");

I've tested that... it turned out to be false. I don't understand the point you were trying to make here.

A diagnostics suggestion, add the following destructor

~Game_Object()
{
    std::cout << "~Game_Object(): " << objName << std::endl;
}

It will tell you that the memory management is not right.

At first I was trying to make copies of the objects and reassign them in the addObject command, but then I decided to simply delete already allocated memory then allocate more memory for new objects and assign the old objects (along with the new one) back to the pointer.

You already have a Game_Object * in obj, you don't have to allocate and assign a new Game_Object ..

obj[i] = new Game_Object[1]; // you don't need this line
obj[i] = tempPtr[i];

Made the change, thank you. As you can see I am still not quite understanding pointer to pointers.

Then strlen() returns the length of a string excluding the terminating NULL character but strcpy copies the string and appends the terminating NULL character <-> you have many one-byte-off memory allocations/assignments/overwrites there.

I did try using strcmp but apparently there were problems comparing a string literal with a char array that had extensive null terminators.

Then an example of a practice you effectively use

struct test
{
    int member_var;
    
    test() : member_var(0){}
    ~test(){}

    void f()
    {
        cout << member_var << endl;
    }

    static test & getObj()
    {
        test * p = 0;
        return *p;
    }
};

int main(int argc, char *argv[])
{
	test & obj = test::getObj();
	obj.f();

	return 0;
}

I think you're asking why I'm returning a reference to NULL in some cases. It's for cases when the user attempts to access memory outside the bounds I defined. Either way they would get NULL returned if they accessed something outside of the boundaries, or will the reference return as void?

I'm not sure what else you could be implying here. It looks like you're returning a reference to a NULL object then using it as if it exists. I don't know where I've done that in my code, honestly. You'd have to give me some line numbers to examine because I don't see at all.

EDIT: I do however see a reason to this reply because I realized that if for some reason someone accessed an object in an Engine_Part and decided to set the reference to NULL then eventually I'd be accessing a NULL reference. I could provide a type of trim method that will resize and reallocate the pointer(s) to prevent this though.

I wonder why are you not using std::string?

I still suggest to drop the manual allocation/reallocation schemes and use a STL container.

Now that I know more about the differences between using strcpy and strlen I will use the std::string class more.

Also the main reason I attempted this project wasn't really to create a workable engine. It was just practice. I wanted to stay away from some of the STL's until I had a better understanding of memory management as well as the C language in general.

// what will 'cmp' be ...
const int cmp = s_manip.compare("abc","abcd");

// what will 'cmp' be ... const int cmp = s_manip.compare("abc","abcd");

I've tested that... it turned out to be false. I don't understand the point you were trying to make here.

My bad ... sorry about that one ...

// what will 'cmp' be ...
const int cmp = s_manip.compare("abc","abcd");

// what will 'cmp' be ... const int cmp = s_manip.compare("abc","abcd");

My bad ... sorry about that one ...

Honestly I'm more thankful than anything.

If I simply stuck to the book I've been reading currently and not coming to these forums my coding would've been incredibly bad, or at least unlearned.

You haven't given me any bad advice so far, so I don't take something "wrong" as an offense whatsoever.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.