Basically, on surfaces that are going to exist right until the program terminates, do I need to run SDL_FreeSurface() for each of them, or would SDL_Quit() take care of all this for me?
I ask mainly because the pointers to a number of my surfaces are class members, and therefore I would need to keep track of each class instance (in a global array or something) if I wanted to run SDL_FreeSurface() on each of their respective surfaces. If SDL_Quit() will do it all in one fell swoop for me, I'd much rather go with that :D
I checked out the SDL 1.2.15 source code to see what actually happens when SDL_Quit is called. Gemini14's answer is correct: SDL_Quit will only free the main SDL_Surface returned by SDL_SetVideoMode.
Here's why:
SDLQuit calls SDLQuitSubSystem to quit every subsystem
SDLQuitSubSystem will call several subsystem quit functions
In particular, SDL_VideoQuit is called.
SDL_VideoQuit first checks if the static global pointer current_video is not NULL.
If current_video is not NULL, the function precedes to clean up several global variables.
SDL_FreeSurface is called on SDL_ShadowSurface or SDL_VideoSurface
SDL_ShadowSurface or SDL_VideoSurface is initialized and returned from SDL_SetVideoMode
Since SDL_FreeSurface is only called on the main SDL_Surface initialized by SDL_SetVideoMode, we can reason that all other SDL_Surface variables allocated memory are not freed with a call to SDL_Quit, and must therefore be freed with explicit calls to SDL_FreeSurface.
However, since generally for all programs the operating system will free the memory automatically when the program ends, freeing the SDL_Surface variables is only a concern if your program continues after SDL_Quit.
It's been a while since I used SDL, but I'm pretty sure SDL_Quit just cleans up the screen surface (the main screen buffer that you set up at the beginning). You have to free the other surfaces you create manually or you get leaks. Of course, since they're already class members, one way to do that easily would be to just free them up in the class destructor.
It is best practise to clear all your surfaces that you know you are using with SDL_FreeSurface().
Similarly, if you create an array of pointers that all call malloc and therefore take up heap space, exiting the program will not clear up all the used space on every system.
int **memspots[1024];
for (i = 0; i < 1024; i++) {
memspots[i] = malloc(1 * sizeof(int *)); // 1024 pointers to ints stored in heap memory
}
At the end of your application, you would definitely want to call free in a similar fashion.
for (i = 0; i < 1024; i++) {
free(memspots[i]);
}
It is only best practise to free any memory used any time you can whenever possible, whether at run time and of course at exit.
My GL texture function for SDL temporarily uses an SDL_Surface to gather some image data (taken from SDL_image) and has this at the end:
if (surface != NULL) // Will be NULL if everything failed and SOMEHOW managed to get here
SDL_FreeSurface();
return;
Related
I created a Vertex Buffer Object class to manage lots of vertices in my application. The user calls the constructor to create a glBuffer and calls glBufferData to allocate a specified amount of space.
There is a class function called resize that allows the user to change the capacity of the VBO by calling again the glBufferData. My question is, how do I deallocate the previous allocation? Or Is it done automatically?
glDeleteBuffer, according to the opengl docs, only deletes the buffer itself with no mention of the actual memory allocated with glBufferData.
Can I keep calling glBufferData on the same bound buffer with no memory leak?
You can't create a memory leak by repeatedly calling glBufferData() for the same buffer object. The new allocation replaces the old one.
There's one subtle aspect that most of the time you don't need to worry about, but may still be useful to understand: There is a possibility of having multiple active allocations for the same buffer object temporarily. This happens due to the asynchronous nature of OpenGL. For illustration, picture a call sequence like this:
glBufferData(dataA)
glDraw()
glBufferData(dataB)
glDraw()
When you make the API call for item 3 in this sequence, the GPU may not yet have finished with the draw call from call 2. It may in fact still be queued up somewhere in the driver, and not handed over to the GPU yet. Since call 2 depends on dataA, that data can not be deleted until the GPU finished executing the draw call 2. In this case, the allocations for dataA and dataB temporarily exist at the same time.
When exactly dataA is actually deleted depends on the implementation. It just can't be earlier than the time where the GPU finishes with draw call 2. After that it could be immediately, based on some garbage collection timer, when memory runs low, or many other options.
glDeleteBuffer() will also delete the buffer memory. Very similarly to the point above, it may not happen immediately. Again, it can only be deleted after the GPU finished executing all pending operations that use the buffer memory.
If you don't plan to use the buffer object anymore, calling glDeleteBuffer() is the best option.
After 10 minutes I read the docs for the glBufferData page.
glBufferData creates a new data store for the buffer object currently bound to
target. Any pre-existing data store is deleted.
,which solves my question. I indeed can keep calling it to increase or decrease the size of my VBO.
glDeleteBuffer delete the buffer handle and the associated resource, if any, should be collected/released soon by the system.
If the buffer is currently binded the driver will unbind it (bind to zero), although it is ugly to delete a binded buffer.
I have a C++ app I'm developing in Linux. I'm allocating some dynamic memory and ultimately calling forkpty(). The child process is calling execl() and as we know, execl() never returns if it succeeds to execute the command. Furthermore, as we know, forkpty() makes a copy of all the parent's data. So, if the child() process never returns control back to my application in order to ultimately do memory cleanup, is it safe to say one better not have any dynamic memory allocated at the time execl() is called from the child process??? I can't believe I could not find this one on here... Thanks in advance.
Allocated memory is part of the process image; when you call
execl, the entire process image is replaced, and any memory in
it simply "disappears" like the rest of it, returning to the OS,
which will then use it elsewhere.
All of the "forked" process memory is freed as part of execl() (if the call is successful).
If this wasn't the case, there would be a lot of memory leaks all over a regular linux system, as it's almost impossible to write anything even a little complex without allocating memory, and, for example, if the arguments to execl() are allocated, you couldn't possibly free them before calling execl().
[SOLVED] Forgot to implement a copy constructor and an assignment operator. The instance which is being assigned to using default copying will get the same pointer as the instance which created the surface it points to. Once one of them destructs or calls redraw(), the other keeps the pointer to freed memory, and it causes a segmentation fault.
I have a class for text labels in my application. When it's properties are changed, it automatically redrawing itself into it's private surface.
Generally, redrawing looks like this:
void Text::redraw() {
if(_font==0) return;
if(_image) {
SDL_FreeSurface(_image); //this line throwing a segfault
_image = 0;
}
_image = TTF_RenderUTF8_Blended(_font, _text.c_str(), _color);
}
But the code crashing on freeing the surface (only a valid ones, of course, as the pointer equals to 0 when it doesn't have a surface to free).
It's also strange that on some machines the code's doing well and frees a memory. But on the others it crashes.
If I comment out lines where it frees a surface, the application works well, but the memory leaks. I didn't found nor explanation, neither a solution for that.
I do set _image to 0 in constructor. There is no code that changes _image value or frees the surface except redraw() function (and destructor).
Somehow freeing memory crashing on XP only. If I comment out freeing part, it doesn't crash. Both variants works on win7 (both x86 and x64) well.
Taking the premise that that we generally know that SDL works well this leaves us with the following options (I can't think of any others, but there may well be some)
Possibility that the library was built incorrectly
The enclosing Text is somehow being copied somewhere else in the code (breaking the rule of 3
Something else is calling SDL_FreeSurface with the same pointer
Something else is trampling on the heap (possibly but unlikely as this is the only instance you've said that fails);
So I'd generally debug this by adding some (grep'able) printfs as follows and then check the output line by line:
void Text::redraw() {
if(_font==0) return;
if(_image) {
fprintf(stderr,"## $%x freeing $%x",this, _image);
SDL_FreeSurface(_image);
_image = 0;
}
_image = TTF_RenderUTF8_Blended(_font, _text.c_str(), _color);
fprintf(stderr,"## $%x allocated $%x",this, _image);
}
I know very little about COM, and searching Google for COM somhow did not find COM at all (probably because it searched .com address instead).
We are using a video capturing hardware. Its SDK allows us to register a callback when a frame is captured. An object interface is passed as a parameter to that callback, and we can get the large buffer address (to the captured frame pixels) and other information by querying to that object.
Now, it looks like calling Release() does not actually delete the memory but decreases the reference count, and when the count reaches 0, it is deleted, right? So, about that large buffer address mentioned above, how about "delete"ing the buffer using the "delete" keyword?
It seems that our program (not written by me, and the person who wrote the program quit the company) copies the pointer to the buffer into some class but never calls any Release() in the callback. Later, the buffer is "delete'd in the class. It seems Release()ing the frame interface object also deletes the buffer. But are they the same?
COM somehow counts the reference but what happens if user's code just deletes that memory? I am sorry if my question is obscure. In short, is it safe to delete a buffer that was gotten from a COM object.
Simplified code: Suspicious situation
void mycallback(IFrame f)
{
char* buffer;
f->GetBuffer(buffer);
MyClass m(buffer);
...
}
MyClass::DeleteBuffer()
{
delete m_buffer;
}
When the code copies the frame buffer content into its own buffer then nothing special happened. The frame buffer is still owned by the COM code, the code's own buffer is still owned by that code. Do not delete the COM buffer, that will invoke undefined behavior when the COM code deletes it too. You should only ever call Release() on a COM interface pointer if you called AddRef() first. In a scenario like this, the AddRef() call was made by the COM code before it invoked the callback. And the Release() call will be made after the callback returns.
Seeing a frame getting copied in a callback is quite normal, the frame buffer normally only stays valid for the duration of the callback. So you have to copy it if you use it later.
If you are chasing a memory leak then this is not likely the culprit. If there was a reference counting problem on the frame buffer then the program couldn't last for more than a minute before having consumed all available memory.
Try to use this place operator delete, CoTaskMemFree
Dealing with COM interfaces is more trickier :-)
Make sure you match the IUnknown::AddRef() and IUnknown::Release() calls
As long as you are in the same context, you can delete the buffer explicitly, even though you got them from a COM interface. But make sure you nullify the pointer after deletion, so that there is no post handling issues.
MyClass::DeleteBuffer()
{
if(m_buffer)
{
delete m_buffer;
m_buffer = null;
}
}
I'm getting a bad error. When I call delete on an object at the top of an object hierarchy (hoping to the cause the deletion of its child objects), my progam quits and I get this:
*** glibc detected *** /home/mossen/workspace/abbot/Debug/abbot: double free or corruption (out): 0xb7ec2158 ***
followed by what looks like a memory dump of some kind. I've searched for this error and from what I gather it seems to occur when you attempt to delete memory that has already been deleted. Impossible as there's only one place in my code that attempts this delete. Here's the wacky part: it does not occur in debug mode. The code in question:
Terrain::~Terrain()
{
if (heightmap != NULL) // 'heightmap' is a Heightmap*
{
cout << "heightmap& == " << heightmap << endl;
delete heightmap;
}
}
I have commented out everything in the heightmap destructor, and still this error. When the error occurs,
heightmap& == 0xb7ec2158
is printed. In debug mode I can step through the code slowly and
heightmap& == 0x00000000
is printed, and there is no error. If I comment out the 'delete heightmap;' line, error never occurs. The destructor above is called from another destructor (separate classes, no virtual destructors or anything like that). The heightmap pointer is new'd in a method like this:
Heightmap* HeightmapLoader::load() // a static method
{
// ....
Heightmap* heightmap = new Heightmap();
// ....other code
return heightmap;
}
Could it be something to do with returning a pointer that was initialized in the stack space of a static method? Am I doing the delete correctly? Any other tips on what I could check for or do better?
What happens if load() is never called? Does your class constructor initialise heightmap, or is it uninitialised when it gets to the destructor?
Also, you say:
... delete memory that has already been deleted. Impossible as there's only one place in my code that attempts this delete.
However, you haven't taken into consideration that your destructor might be called more than once during the execution of your program.
In debug mode pointers are often set to NULL and memory blocks zeroed out. That is the reason why you are experiencing different behavior in debug/release mode.
I would suggest you use a smart pointer instead of a traditional pointer
auto_ptr<Heightmap> HeightmapLoader::load() // a static method
{
// ....
auto_ptr<Heightmap> heightmap( new Heightmap() );
// ....other code
return heightmap;
}
that way you don't need to delete it later as it will be done for you automatically
see also boost::shared_ptr
It's quite possible that you're calling that dtor twice; in debug mode the pointer happens to be zeroed on delete, in optimized mode it's left alone. While not a clean resolution, the first workaround that comes to mind is setting heightmap = NULL; right after the delete -- it shouldn't be necessary but surely can't hurt while you're looking for the explanation of why you're destroying some Terrain instance twice!-) [[there's absolutely nothing in the tiny amount of code you're showing that can help us explain the reason for the double-destruction.]]
It looks like the classic case of uninitialized pointer. As #Greg said, what if load() is not called from Terrain? I think you are not initializing the HeightMap* pointer inside the Terrain constructor. In debug mode, this pointer may be set to NULL and C++ gurantees that deleting a NULL pointer is a valid operation and hence the code doesn't crash. However, in release mode due to optimizations, the pointer in uninitialized and you try to free some random block of memory and the above crash occurs.