Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

Dark GDK / std::bad_alloc - Error

Author
Message
Red Eye
15
Years of Service
User Offline
Joined: 15th Oct 2008
Location:
Posted: 24th Oct 2010 23:46
Hey,

I am getting the folowing error:


And it points out to the folowing code:


But I seriously think it has to do with my crappy string2Char() conversion.



Any ideas on how to solve this problem, if I need to give any other information, I am happy to share.

Does this error means my new[] has failed, and cant allocate any memory, if so is there any fix for this?

Thanks,

Red Eye

Michael P
18
Years of Service
User Offline
Joined: 6th Mar 2006
Location: London (UK)
Posted: 25th Oct 2010 00:45
You are right, its your string2Char function. delete[] never gets called because the function returns before this. As a result you have a memory leak, which means that eventually the application consumes the maximum amount of memory that windows will allow it to and so you get a bad_alloc error.

Red Eye
15
Years of Service
User Offline
Joined: 15th Oct 2008
Location:
Posted: 25th Oct 2010 00:57 Edited at: 25th Oct 2010 00:59
Thanks for the info, mate.

But declaring char* temp = a; and then delete a and return temp would that work? Doesnt sound logical to me, or isnt that the way?

Gonna try.

Edit: I am not getting the error anymore, very happy now, but now i am getting a Access violation reading location 0xfeeefeee. Going to do some googling about that.

Michael P
18
Years of Service
User Offline
Joined: 6th Mar 2006
Location: London (UK)
Posted: 25th Oct 2010 00:59
No because temp would point to the same memory location as a, so when you delete a, the memory pointed to by both a and temp is freed.

You can't deallocate the string until its no longer needed, so the user of the function should call it manually and it shouldn't be a part of the function itself.

Red Eye
15
Years of Service
User Offline
Joined: 15th Oct 2008
Location:
Posted: 25th Oct 2010 01:03 Edited at: 25th Oct 2010 01:04
I see. Thanks for the info again mate.

But thats really frustrating. So basicaly i would need some sort of a destructor do delete them, everytime I call the function.
I use that function like 10-40 times over!?

Michael P
18
Years of Service
User Offline
Joined: 6th Mar 2006
Location: London (UK)
Posted: 25th Oct 2010 01:07
I usually do one of the following:
1. Create a string class which does lots of fun stuff, as well as automatically deallocating memory. Then you can use this in the same way you use the std::string class, except you can customize it nicely.

2. Use delete[] after every call to string2Char, and after the returned string does not need to be used anymore.

Red Eye
15
Years of Service
User Offline
Joined: 15th Oct 2008
Location:
Posted: 25th Oct 2010 01:11 Edited at: 25th Oct 2010 01:12
Sorrry for double post, but for example my char2String function works quite well , and i find it quite neat, but on the other hand there might be a better way:



Pitty i cant inverse the methode. Or can we?

Edit: We posted on the same time, didn saw yours.

Those are 2 really neat tips, thanks, will try right now.


pirogoth
16
Years of Service
User Offline
Joined: 6th Apr 2008
Location: Good Old California
Posted: 25th Oct 2010 03:28
@Red Eye
You're close. That is the way you should go about converting character arrays into an std::string. However, he wants to do the opposite. He wants to convert strings to character arrays.

@Original Poster
Strings in the STD namespace have a method for doing just this.
Cuddle Bunniezzz 12
15
Years of Service
User Offline
Joined: 14th Jan 2009
Location: Buffalo, NY
Posted: 25th Oct 2010 06:02
You could also do something like this:

const_cast<char *>(string.c_str())

Example:


http://ref.darkgdk.us/ <- Online DarkGDK Refernece. More content coming soon.
pirogoth
16
Years of Service
User Offline
Joined: 6th Apr 2008
Location: Good Old California
Posted: 25th Oct 2010 10:32
@Cuddle Bunniezzz 12
Good call. Entirely forgot that the c_str() method returns a constant character pointer. Thanks!
Red Eye
15
Years of Service
User Offline
Joined: 15th Oct 2008
Location:
Posted: 25th Oct 2010 12:12
Hey,

Thanks for the help mates, but i do believe calling const_cast<char*>(toconvert.c_str()) isnt very clean, on the long go it would be very unaccurate, (wich i just experienced). Altough thanks mates!

Red Eye
15
Years of Service
User Offline
Joined: 15th Oct 2008
Location:
Posted: 25th Oct 2010 13:06 Edited at: 25th Oct 2010 13:44
Nevermind, epic failure.

Red Eye
15
Years of Service
User Offline
Joined: 15th Oct 2008
Location:
Posted: 25th Oct 2010 16:04


Would result in this:



dark coder
21
Years of Service
User Offline
Joined: 6th Oct 2002
Location: Japan
Posted: 25th Oct 2010 17:36
Quote: "but i do believe calling const_cast<char*>(toconvert.c_str()) isnt very clean"


And it's not supposed to, you only have to remove the constness because GDK's poorly written.


Quote: "Would result in this:"


Wow, don't do that, ever. In that code there's no correlation between the existence of the input string and the returned pointer, so it's amazingly easy to break everything as you're seeing.

What you should be doing is wrapping dbText or whatever to take a string as input and you just (char*)blah.c_str() and feed that to the function, without returning anything, don't ever store the c_str() pointer like your function would allow you to.

Red Eye
15
Years of Service
User Offline
Joined: 15th Oct 2008
Location:
Posted: 25th Oct 2010 17:45 Edited at: 25th Oct 2010 17:58
@dark coder: A dark coder with a bright mind . Thanks for clearing that up. Gonna try that right now.

Edit: Wow I did what you said, and it compiled. But now i think its something else that is giving me the std::bad_alloc because i got the error again. And its pointing out to the dbLoadObject() part...

What things can let the std::bad_alloc error appear? I thought that only new could do that?!

Screen where it is pointing too:



O wait should i delete it after? ...the char?


dark coder
21
Years of Service
User Offline
Joined: 6th Oct 2002
Location: Japan
Posted: 25th Oct 2010 18:29
Stop storing the c_str() result! Hairy old men will rape you if you continue to do this(no joke).

bad_alloc is thrown when Windows can't give you the requested memory, so you must be dong something stupid like loading a million models in the main loop. While you're not directly using new, the functions you call are, i.e. dbLoadObject. It's also possible that the model you're trying to load is causing GDK to die, try loading a model you know should work, like the ones that come with the GDK examples. You could also monitor your memory usage from the task manager.


Quote: "O wait should i delete it after? ...the char?"


No, because there will be no char* to delete(see above).

Red Eye
15
Years of Service
User Offline
Joined: 15th Oct 2008
Location:
Posted: 25th Oct 2010 19:02 Edited at: 25th Oct 2010 19:17
O wait. So i can't store it to somewhere? Daimn, okay, will try to implement that. EDIT: <<< Did that. Gave me still a bad_alloc error, then i tried another model, and it worked, but my model worked before i had std:bad_alloc error. Anyway, i unzip a zip file(wich contains the model) with this:



It might be because of that that the universe.dbo is wrong? Maybe even currupted? Will try and load it in a modeling package and see wahts wrong.

Michael P
18
Years of Service
User Offline
Joined: 6th Mar 2006
Location: London (UK)
Posted: 25th Oct 2010 19:40
I think you should learn how pointers work before using them, there's plenty of good guides on the net.

IanM
Retired Moderator
22
Years of Service
User Offline
Joined: 11th Sep 2002
Location: In my moon base
Posted: 25th Oct 2010 19:48
@Red Eye,
Just because you get a bad_alloc exception when you are loading a model, doesn't mean that the model has a problem - it means that your code has a problem. The memory leaks you are experiencing could happen anywhere.

Seeing as everything up to this point has been about the strings that the libraries return and your misunderstandings of how to deal with them, I'd guess that this is still happening due to that.

Admittedly, it's because of the string handling that I don't use the GDK as much as I probably should - the boost shared_array and scoped_array are useful for dealing with this specific kind of problem.

Utility plug-ins (26-JUL-2010)
I'm applying terms of use that require you to wear a red nose and honk a horn whenever you use the Internet
Red Eye
15
Years of Service
User Offline
Joined: 15th Oct 2008
Location:
Posted: 25th Oct 2010 20:59 Edited at: 25th Oct 2010 21:01
Quote: "because of the string handling that I don't use the GDK "


:S Okay. But till now I havnt been working with gdk on the problem i am having... only c

Quote: "
Just because you get a bad_alloc exception when you are loading a model, doesn't mean that the model has a problem - it means that your code has a problem. The memory leaks you are experiencing could happen anywhere."


Dark Coder suggested that to me, wich i found a very nice idea, and indeed the unverse.dbo wasnt unzipped right, it had 0bytes wich ofcourse isnt correct, i changed the code of unzipping and it works (the unzipping part) it still has the error tho.

Quote: "Seeing as everything up to this point has been about the strings that the libraries return and your misunderstandings of how to deal with them, I'd guess that this is still happening due to that."


Actually it is : the chars that the function should return. But anyway yeah my knowledge about how to convert a string 2 char is pretty basic, I just can handle with char* blah = new... so for that i would need delete, but i was searching for other ways around before building a class that does that for me as Michael P suggested.

Quote: "the boost shared_array and scoped_array are useful for dealing with this specific kind of problem."

Thanks for the tip!

@Michael P: Ty for the tip mate, indeed i dont know much about pointers i find them buggie sometimes, but on the other hand i cant handle them right either.

Thansk for the help anyways guys.

Mireben
16
Years of Service
User Offline
Joined: 5th Aug 2008
Location:
Posted: 25th Oct 2010 22:51 Edited at: 25th Oct 2010 23:01
Regarding your char2String function: just saying that you don't need a whole complicated function to do that because strings are prepared to do that conversion themselves. Just pass the char pointer to the string constructor, or assign it with the assignment operator and it will copy the string for you.

Red Eye
15
Years of Service
User Offline
Joined: 15th Oct 2008
Location:
Posted: 26th Oct 2010 11:05
This is really frustrating:



I don't understand, this results in garbage, and when i delete delete[], it works. But i need to call delete[] somewhere and i called it after everything was initizalized.

Mireben
16
Years of Service
User Offline
Joined: 5th Aug 2008
Location:
Posted: 26th Oct 2010 19:13 Edited at: 26th Oct 2010 19:15
This cannot be answered without more info:
1. Is pathtodynobjfile_char a pointer to char buffer, which you allocated with new somewhere?
2. What does your fe_addDebugString function do, how is it coded?
3. What is exactly the "garbage" result you got? (Something like the screenshot above?)
Red Eye
15
Years of Service
User Offline
Joined: 15th Oct 2008
Location:
Posted: 26th Oct 2010 20:53 Edited at: 26th Oct 2010 21:30
1. Is pathtodynobjfile_char a pointer to char buffer, which you allocated with new somewhere?

new char[] ... converted from a string.

2. What does your fe_addDebugString function do, how is it coded?

It basicaly stores it to a char array, wich will be printed in the debug window.

3. What is exactly the "garbage" result you got? (Something like the screenshot above?)

Yes, something like that.

Bytheway really thanks all for your time trying to help me!!! Really apreciate that!

Edit: nvm...

Mireben
16
Years of Service
User Offline
Joined: 5th Aug 2008
Location:
Posted: 26th Oct 2010 22:06 Edited at: 26th Oct 2010 22:10
You say "when i delete delete[], it works". This leads me to believe that somehow the fe_addDebugString function stores a pointer rather than a copy of the string. But I can't tell without seeing the complete function. That's the only guess I have because there is no obvious problem in the latest code snippet that you posted. (Copying the strings before passing them to fe_addDebugString is not really necessary - supposing that fe_addDebugString works correctly - but that's optimization issue, not a bug.) The problem should be located inside the function.

EDIT: The "converted from a string" part is a bit suspicious too, but whatever you did with the char arrays before this code snippet doesn't really matter, since you use strcpy to fill them with new content here. As long as the length does not overflow, those should be OK, so my primary suspect is still the function.
Red Eye
15
Years of Service
User Offline
Joined: 15th Oct 2008
Location:
Posted: 26th Oct 2010 23:55 Edited at: 26th Oct 2010 23:56
Alright, i am sure it is that function.

But in the meantime i created a class. Would you like to take a look at it and see if its alright? It works so far at least.

Here is full source code of that particular test:
(I still practising with this ... )




Code of function:



Cheers,

RedEye

Mireben
16
Years of Service
User Offline
Joined: 5th Aug 2008
Location:
Posted: 27th Oct 2010 09:11
Let's start with the fe_addDebugString function. If the debugtxt is an array of std::string then it's OK but if it's an array of char pointers - I suspect it is - then this instruction:
stores only a pointer, it does not copy the string. That's why the content gets destroyed when you delete[] the original pointer after using the function.

I mentioned that copying the string with strcpy before passing it to the function would not be necessary, but it would be necessary inside the function, if you want to store it. But for that, each slot of the debugtxt array must point to a valid, allocated char buffer.

Now about the new FESTRING class. There is still a memory leak in that, because every time the convert2Char function is called, you allocate a new string without deleting the previous one. To use that class without memory leak, every time you want to convert something, you have to construct the class, then destroy it after use, instead of being able to construct it once and call convert2Char repeatedly for different strings.

Another problem is that the pointer = "" in the constructor does not mean that the pointer is "empty". It means that the pointer is valid but points to an empty string (which is located in your program text). The way to create an empty pointer is to set it to zero, meaning it points to nothing. (It's good to know that it is always safe to delete[] a zero pointer.)

The way to solve the problem is either to include delete[] into the convert2Char function before allocating the new string, or to allocate the string in the constructor once and for all, but then you have to estimate the maximum string length you are going to need.

To be honest, I don't understand why you are desperately trying to force this conversion and store the result. My general advice, which would be a solution to all your problems: keep your strings always in std::string format and do not convert them until the very last moment when you absolutely have to. When you need to pass an std::string to a Dark GDK function which expects a char pointer, it is very easy to include the c_str() into the function call, without storing the conversion result. This is a small price to pay for keeping the rest of the code simple, clean and (mainly) memory-safe. Take your test code above, it can be written without any conversion function, and shorter:



The (char*) typecast shortens the typing, the official version would be the const_cast recommended by dark coder above, but this works as well.

One more small thing. Notice that in the code above I changed the include "string.h" to include <string>. Usually you should use this "new style" include, without extension and with < these brackets, whenever the compiler allows it. Omitting the extension means C++ header, and the < brackets mean this file should be searched first in the system directories. With "" the file is searched in your program directory first where your own source code files are.
Red Eye
15
Years of Service
User Offline
Joined: 15th Oct 2008
Location:
Posted: 27th Oct 2010 15:44 Edited at: 27th Oct 2010 15:47
Thank you very much for the information. I will aply this information , thank you very much.

But one slightly problem, say i am working with a string and after edited it in any way, i need to pass it to a darkgdk and then edit it once again, so i need to modifie a string quite a bit, but ofcourse i can use (char*)mystring.c_str(). Thanks for the info mate!

IanM
Retired Moderator
22
Years of Service
User Offline
Joined: 11th Sep 2002
Location: In my moon base
Posted: 27th Oct 2010 15:59
That class doesn't handle copying in any way and will therefore do the wrong thing. It will also leak memory.

I've cleaned up the code, but TBH, I'm not convinced that this class is the best way to deal with the problem despite that:


I'll have a think about the general problem and try to come up with a cleaner general solution that fits with GDK and doesn't need you to work harder.

@Mireben,
Including string.h is perfectly OK, as long as you only want access to the C functions, which is all Red Eye needs for his code.

Utility plug-ins (26-JUL-2010)
I'm applying terms of use that require you to wear a red nose and honk a horn whenever you use the Internet
Mireben
16
Years of Service
User Offline
Joined: 5th Aug 2008
Location:
Posted: 27th Oct 2010 21:22
Thank you for the information about the header usage. I thought it's always recommended to use the C++ headers, but now the picture is clearer.
Red Eye
15
Years of Service
User Offline
Joined: 15th Oct 2008
Location:
Posted: 28th Oct 2010 10:43
Thanks IanM for your help, I managed to make a new class Thanks for your tips.

Thanks everyone for his time! I really apreciate it.



Red Eye
15
Years of Service
User Offline
Joined: 15th Oct 2008
Location:
Posted: 28th Oct 2010 21:00 Edited at: 28th Oct 2010 21:03


Okay So this is very wierd, that is my egStringClass...

I use it for loading dbo file:
(the path is totally right)



It still gives me the error...
Another place where i use it:

(the path is totally right)



Mireben
16
Years of Service
User Offline
Joined: 5th Aug 2008
Location:
Posted: 28th Oct 2010 21:32
What's the error this time, is it still bad_alloc? The only obvious problem I see at first sight is that you shouldn't call the destructor directly. Remove these lines:



Since the string objects are local, when the function finishes, they will be automatically destroyed. If you call the destructor and then the system also tries to destroy the object, it can lead to an error. I have no other guesses at the moment. If this doesn't help, try to step through the code to see which line throws the error.
IanM
Retired Moderator
22
Years of Service
User Offline
Joined: 11th Sep 2002
Location: In my moon base
Posted: 28th Oct 2010 23:26 Edited at: 28th Oct 2010 23:27
Yes, don't call the destructor yourself.

In addition:
- you don't need to check for NULL when doing a delete - the compiler already checks for that and turns a delete or delete[] of NULL into a no-op.
- Your operator== does a strcmp of two pointers, one or both of which could be NULL. That's listed as undefined behaviour in the standard, which means it could do anything from work, crash or hack the pentagon.
- get_input and operator<< use iostreams - no such thing in GDK.

Apart from those minor issues, very well done if you wrote that class yourself.

Utility plug-ins (26-JUL-2010)
I'm applying terms of use that require you to wear a red nose and honk a horn whenever you use the Internet
Red Eye
15
Years of Service
User Offline
Joined: 15th Oct 2008
Location:
Posted: 28th Oct 2010 23:54 Edited at: 29th Oct 2010 00:01
Quote: "Apart from those minor issues, very well done if you wrote that class yourself."


Wahah... I did wrote it, but folowing a tutorial + folowing loads of lectures by Richard Buckland. But as the tutorial said: "Actually a nonsense class as the STL (string) class should do that + loads more for yah." <something like that anyway

Anyway I have learnt alot folowing tuts and lectures and writing that code. I recommend everone folowing all the lectures by Richard Buckland he's very good.

Anyway...


Thanks for the advice IanM and Mireben! I will see if it works!

Quote: "- Your operator== does a strcmp of two pointers, one or both of which could be NULL. That's listed as undefined behaviour in the standard, which means it could do anything from work, crash or hack the pentagon.
- get_input and operator<< use iostreams - no such thing in GDK."


yeah get_input was included in the tutorial. I wrote it down and it works with #include <iostream> in a console app.
But regarding your second point, it should work, at least so far I tested...

Edit: It does not. I mean i still dont understand why it cant allocate memory , there are just 2 new chars.... is that such a big deal for a computer , I find it quite wierd, maybe it's something else!

This is my level loading function (wich is in class)...



The class is called with this:

gLevel.update();

IanM
Retired Moderator
22
Years of Service
User Offline
Joined: 11th Sep 2002
Location: In my moon base
Posted: 29th Oct 2010 01:24
Quote: "Actually a nonsense class as the STL (string) class should do that + loads more for yah."

True, but only if it does what you need it to do. Having started on your own string class, you can continue to customise it - you can't do that with std::string directly. You could make your class use std::string internally though...


You call your destructor, it deletes the memory you allocated. Then C++ calls your destructor, and deletes the same memory again.

Here's a very rough and early version of something I've just thrown together:


You can write further member functions to cut pieces of the string out, but always return the value in terms of 'cs' - delete the current content, create a new 'cs' containing the return value, then return that pointer.

Utility plug-ins (26-JUL-2010)
I'm applying terms of use that require you to wear a red nose and honk a horn whenever you use the Internet
Red Eye
15
Years of Service
User Offline
Joined: 15th Oct 2008
Location:
Posted: 3rd Nov 2010 23:12
@IanM: Really srry for the late responds. Anyway, thats looks really good mate!!! Good work... I will test it!

Anyway, I am going to check if I can do it another way, else i will bother you guys again if you dont mind.

Thanks all for the help,

RedEye

Login to post a reply

Server time is: 2024-10-02 11:30:58
Your offset time is: 2024-10-02 11:30:58