• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
lipsryme

(impossible?) Memory leak problem

16 posts in this topic

Ok so while still reducing the main function to this:
Which is basically just the main entry function for a win32 application and a return 0 at the end.
He's still giving me a memory leak output at the exact line of the "[b]_CrtDumpMemoryLeaks();[/b]" call.
How is this even possible ? Is it a bug ? Or is windows somehow leaking memory ?
It also doesn't let me break at those allocs.

[CODE]
/*
****************************************************
Main.cpp - Source File
Usage: Implements Main-Entry function
****************************************************
*/

// Header for memory leak search
#ifdef MEM_DEBUG
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#endif
#define _USE_MATH_DEFINES
// Includes
#include "../Framework/Engine/Core/Engine.h"
#include <cmath>

//***********************************************************
//* WinMain (int)
//* Usage: Win32 Entry-function
//* Parameters:
//* - Handle to applications instance (HINSTANCE)
//* - PreviousInstance <unused> (HINSTANCE)
//* - CommandLine string (LPSTR)
//* - CommandLine parameter (int)
//**********************************************************
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nShowCmd)
{
// Search for memory leaks
#ifdef MEM_DEBUG
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF |_CRTDBG_LEAK_CHECK_DF );
_CrtDumpMemoryLeaks();
//_CrtSetBreakAlloc(147);
#endif

//// Define information of our engine
//EngineDescription engineDesc;
//// Window
//engineDesc.windowDesc.Windowed = true;
//engineDesc.windowDesc.hasBorder = false;
//engineDesc.windowDesc.windowTitle = L"DirectX11 based Engine";
//engineDesc.windowDesc.windowWidth = 1280;
//engineDesc.windowDesc.windowHeight = 720;

//// Graphics
//engineDesc.graphicsDesc.VSync = false;
//engineDesc.graphicsDesc.viewport.TopLeftX = 0.0f;
//engineDesc.graphicsDesc.viewport.TopLeftY = 0.0f;
//engineDesc.graphicsDesc.viewport.MinDepth = 0.0f;
//engineDesc.graphicsDesc.viewport.MaxDepth = 0.999f;
//engineDesc.graphicsDesc.viewport.Width = (float)engineDesc.windowDesc.windowWidth;
//engineDesc.graphicsDesc.viewport.Height = (float)engineDesc.windowDesc.windowHeight;
//engineDesc.graphicsDesc.rasterizer_state.fillMode = FM_Solid;
//engineDesc.graphicsDesc.rasterizer_state.cullMode = Cull_Back;
//
//// Global Illumination
//engineDesc.graphicsDesc.GlobalIllumination.SSAO.useSSAO = false;

//// Post Processing
//engineDesc.graphicsDesc.postFXDesc.DepthOfField = false;
//engineDesc.graphicsDesc.postFXDesc.ColorCorrection = false;
//engineDesc.graphicsDesc.postFXDesc.VolumetricScattering = false;
//engineDesc.graphicsDesc.postFXDesc.PostAA = false;
//
//
//// Camera
//engineDesc.cameraDesc.type = Free;
//engineDesc.cameraDesc.MoveSpeed = 0.5f;
//engineDesc.cameraDesc.RotationSpeed = 2.0f;
//engineDesc.cameraDesc.cameraPosition = XMFLOAT3(0.0f, -0.25f, -1.0f);
//engineDesc.cameraDesc.cameraUp = XMFLOAT3(0.0f, 1.0f, 0.0f);
//engineDesc.cameraDesc.cameraTarget = XMFLOAT3(0.0f, 0.0f, 1.0f);
//engineDesc.cameraDesc.nearClip = 0.05f;
//engineDesc.cameraDesc.farClip = 500.0f;
//engineDesc.cameraDesc.FoV = 55.0f;
//engineDesc.cameraDesc.Aspect = (float)(engineDesc.windowDesc.windowWidth / (float)engineDesc.windowDesc.windowHeight);
//


// Initialize our engine
//Engine* engine = new Engine(engineDesc);

// Start our engine
//engine->Run(new Scene(engine));

//// Release allocated memory
//if(engine)
//{
// delete engine;
// engine = NULL;
//}

return 0;
}
[/CODE]


And the following output:

Detected memory leaks!
Dumping objects ->
{147} normal block at 0x009F5710, 80 bytes long.
Data: < W W W > 10 57 9F 00 10 57 9F 00 10 57 9F 00 CD CD CD CD
{146} normal block at 0x009F1AD0, 8 bytes long.
Data: < > D4 88 CC 01 00 00 00 00
Object dump complete. Edited by lipsryme
0

Share this post


Link to post
Share on other sites
[quote name='lipsryme' timestamp='1352722767' post='5000207']
Which is basically just the main entry function for a win32 application and a return 0 at the end.
[/quote]
Have you checked your code for static variable declarations ([s]aka [/s]globals/class variables) ? Do you clean them up ? You are including Engine.h and most likely are linking some static libs here ? Edited by Ashaman73
2

Share this post


Link to post
Share on other sites
I'd suggest that you're being overly paranoid about memory leaks at too early a stage. Windows (and any other modern OS) has per-process virtual memory, and will automatically free all memory at process exit anyway, so even if _CrtDumpMemoryLeaks is reporting a leak, it's not actually a leak that you need to be too concerned about - it's going to be freed during normal app tear-down.

No, you very probably haven't found a bug in Windows that nobody else in the world is aware of. ;) Over 99% of the time when people make this diagnosis, the error is ultimately traceable to something in their own code, or a misunderstanding of how things work behind the scenes, so most likely explanation is what Ashaman73 said - your .h file is causing something to be initialized, or you have global declarations somewhere else.
1

Share this post


Link to post
Share on other sites
[quote]
Have you checked your code for static variable declarations (aka globals ie. class variables)
[/quote]
You need to check for static variables [u]and[/u] global variables (the two are not the same). Static variables can file file, class or function local. A global variable can be written as "int x", with the appropriate "extern" declarations visible at the point of use.

AKA, meaning "Also Known As", implies that "static" and "global" are the same. Your usage of "i.e.", which means "that is", says that all globals are class variables, which is also not true. You should use "e.g." meaning "for example".
2

Share this post


Link to post
Share on other sites
[quote name='rip-off' timestamp='1352725463' post='5000220']
AKA, meaning "Also Known As", implies that "static" and "global" are the same.
[/quote]
Yep, you are right, I was mixing the more c-like globals and static class members [img]http://public.gamedev.net//public/style_emoticons/default/smile.png[/img]
0

Share this post


Link to post
Share on other sites
Hmm well I'm not really using any static dynamically allocated variables. Some 3rd party stuff might. Even so without including anything else than <windows.h> it's still giving me the same leaks. Is this something I can ignore then?

Ashaman73: "You are including Engine.h and most likely are linking some static libs here ?"
Does that make any difference even if I'm not including it at all ? Edited by lipsryme
0

Share this post


Link to post
Share on other sites
There are parts of the standard library which will create static objects at the inclusion point (thus before your main function starts). This makes it possible, for example, to use std::cout without constructing a stream object manually. The standard containers will also create objects for memory allocation and such. As these objects are initialized before main, they will only be deleted after your program has ended. Therefore you cannot track memory allocation of these objects from inside your program. It has been a while, but I believe I switched to STLport at the time, which had some compiler directives to surpress this behaviour.

HTH
0

Share this post


Link to post
Share on other sites
Well okay so I've managed to trace it back to the fbx sdk. Not sure how to proceed though. Don't think there's anything I can do.
Might be just when using its debug libraries.
0

Share this post


Link to post
Share on other sites
This is an interesting problem with static variables. Since you call CrtDumpMemoryLeaks() before main() exits, static variables which allocate memory (which get destructed after main() exits) will still show as memory leaks. To avoid this false positive, don't call CrtDumpMemoryLeaks() manually. The _CRTDBG_LEAK_CHECK_DF flag effectively adds the memory leak dump as an atexit() call, which happens at the very end of the program. Edited by Qanael
2

Share this post


Link to post
Share on other sites
[quote name='rip-off' timestamp='1352725463' post='5000220']AKA, meaning "Also Known As", implies that "static" and "global" are the same. Your usage of "i.e.", which means "that is", says that all globals are class variables, which is also not true. You should use "e.g." meaning "for example".
[/quote]

First smirk of the day award goes to rip-off.

[quote name='Qanael' timestamp='1352774353' post='5000432']
This is an interesting problem with static variables. Since you call CrtDumpMemoryLeaks() before main() exits, static variables which allocate memory (which get destructed after main() exits) will still show as memory leaks. To avoid this false positive, don't call CrtDumpMemoryLeaks() manually. The _CRTDBG_LEAK_CHECK_DF flag effectively adds the memory leak dump as an atexit() call, which happens at the very end of the program.
[/quote]

This. I was about to look up the function there because I suspected that this was the case.

Memory leak detectors work by reporting on anything that's still allocated when they are invoked (they hook the allocation and deallocation functions to keep track). So if you're calling the function prior to the end of the program then anything that's still allocated will be reported on.

I'd also recommend checking out [url="http://vld.codeplex.com/"]VLD[/url]. Someone here suggested it to me and I tried it and love it. You can just double-click the message in the report to go straight to the leaky allocation in the code. Edited by Khatharr
1

Share this post


Link to post
Share on other sites
No one really saw it? Really???

There's a lot that goes on after leaving main(); hence why it's telling you there are leaks.
Try using [url="http://www.cplusplus.com/reference/clibrary/cstdlib/atexit/"]atexit[/url].

Personally, I prefer to create a static object, ensure it's the first one to get created, and then let the C++ compiler clean up last:

[source lang="cpp"]class MeFirst
{
MeFirst() {}
~MeFirst() { /* -- call CRT debug dump here -- */ }
static MeFirst&amp; getSingleton()
{
static MeFirst instance;
return instance;
}
}

int main()
{
//Calling first may ensure the static initialization goes first.
volatile MeFirst &amp;doThisFirst = MeFirst::getSingleton();
return 0;
}[/source]

It's out of my head, and beware I may be missing a case where another static variable gets initialized before this one, hence you may still get leaks (before it will be destroyed after CRT dump). Anyway, try different approaches, google a little, experiment, and find out how to make the CRT Dump get truly called last.
wxWidgets manages to do it correctly, you may want to take a look there.

Cheers
Dark Sylinc

[b]Edit:[/b] Oh, and Singleton is an evil pattern. Don't use it. This is an exception because you're not actually using it. Edited by Matias Goldberg
0

Share this post


Link to post
Share on other sites
Why would you use a singleton to implement something that doesn't need implemented?

[quote name='Qanael' timestamp='1352774353' post='5000432']The _CRTDBG_LEAK_CHECK_DF flag effectively adds the memory leak dump as an atexit() call,[/quote]

Additionally, there's absolutely no guarantee that instantiating 'first' will make that object deconstruct last. Additionally, if he's getting leaks from just including a header file then obviously he's got something doing allocations prior to main(), so being 'first' by instantiating in main isn't possible and there's explicitly no defined order for global or static initializations across compilation units. Edited by Khatharr
0

Share this post


Link to post
Share on other sites
[quote name='Khatharr' timestamp='1352939513' post='5001051']
Additionally, there's absolutely no guarantee that instantiating 'first' will make that object deconstruct last.
[/quote]

Actually, I am pretty sure there is a guarantee that destruction of static objects will happen in the reverse order of construction (more precisely, the end of construction).
1

Share this post


Link to post
Share on other sites
[quote name='Khatharr' timestamp='1352950444' post='5001088']
I misspoke. I meant in the context of the 'pre-main' objects.
[/quote]
I am not sure if you misspoke or you misunderstood: The static objects I am referring to are meant to contain what you call "pre-main" objects.

If I remember the rules correctly, within a translation unit (a .cpp file), global objects are constructed in the order they are defined, but there is no guarantee of what order things in different translation units will be constructed (which means there is no solution that guarantees your object will be "first", unless it's something specific the compiler provides). Static local variables are constructed on the first function call where they are needed (which could be as part of the construction of some other static object). Then destructors will be invoked in the reverse order of when the constructors finished.

As an example of how these guarantees can be useful, think of a program that has a singleton implementation of a log. If a global object wants to write something out to the log at destruction (statistics of usage or what have you), you need to make sure that the log gets destructed later than the global object. The global object can guarantee this by using the log from the constructor (all you need is something like Log::get_instance(), even if you do nothing with it). Then the log's constructor is guaranteed to have finished before the object's constructor, and destructors will be called in the right order.

DISCLAIMER: After one attempt at trying to be clever about these things, I decided that the advice to not use global variables of any type is golden, and I strongly discourage people from doing what I described in the paragraph above. Don't use global variables, or singletons, or static local variables, or static member data, and you'll save yourself some really bad headaches.
0

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  
Followers 0