memory problems

I am using VS2008.
I have a Windows Service application which creates Crystal Reports. This is
a multi theaded application which can run several reports at one time.
My problem - there is a memory leak someplace. I can not detect the memory
leak by running several reports by hand, but when I run tha app as a
servrice and process few hundred reports there is significant memory leak.
The application can consume over 1GB of memory where it should not go over
200 mb. I have few other applications that use Crystal Reports and those
applications do not have memory leak, the big difference is those
applications are single threaded.

My question: are there any tools, books, tutorials that can help me to find the memory leak?
There aren't any book, or tool which can help you find and solve your memory leak problem rapidly and directly. :)
But the cause : Yes. Here are several causes :
1- You allocated dynamic memory (pointers) but you forgot to delete (free) them.
2- Your structures have a lot of members, probably this means not all variables are used completely, so also it may cause memory leak.

Edit : Sorry, maybe my first answer is wrong :)
Last edited on
Of course there are dedicated tools for that, like Visual Leak Detector and many others :

http://vld.codeplex.com/

However, you cannot easily debug a windows service as it is, just debug your EXE as any normal console applicaton (it could be required to first change your application code to be able to do that, it depends how it is written)
Last edited on
I can recommend to read a book "Effective C++" and you can read in wikipedia or softpedia about different debuggers (VLD, Purifu, MemCheck, DrMemory, Deleaker). Also, read about object oriented programming.
I get it. Perhaps you can share books or links to a good library?
Just search in google))
You may use some block code to detect memory leak. (Where you doubt)

Good luck.
What block? I've never heard about it. Maybe I do not quite understand you.
Ok, Please, check the Task Manager.

"Block code" in my opinion is the code which is only used to debug (usually complex programs) that standard debug feature cannot.
Some functions which can do this effectively (which I'm currently using in many big projects) :


- Sleep();
- exit();
- ExitProcess();
- MessageBox();
- FatalAppExit();
- sprintf, printf


1
2
3
int *var;

*var = 10; //Crash! 


1
2
3
4
int *var;
MessageBox(0,"Hahahaha","Hihihi",0);
*var = 10; 
MessageBox(0,"HoHoHoHo","Hihihi",0); //"Hohohoho" is never reached -> The problem here - *var = 10; 


About your memory leak : You also can use this to watch your program progress (with your Task Manager) A very simple example :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void SetValue(double *var, double value)
{
     var = new double(); //Suppose you forgot to free "var"
     *var = value;
}

int main()
{
double *a, b, c;

b = 10;
c = 15;
for(int i = 0;i < 10000000;i++)
{
     SetValue(a, i);
     b = pow(*a, 2);
     c = pow(b, 2);
}
return 0;
}

Certainly It causes memory leak.

Now, you put some block code, for example :

1
2
3
4
5
6
7
for(int i = 0;i < 10000000;i++)
{
     SetValue(a, i);b = pow(*a, 2);c = pow(b, 2);

     Sleep(1); //Sleep block command
}
MessageBox(0,"Done.","!!!",0); //MessageBox block command 


Now you open up the Task Manager and see the program memory-consuming grows up and up. Test it, and you will see.

Another example :
1
2
3
Sleep(5000);
function([...]); //which is very questionable
MessageBox(0,"Done.","!!!",0);

Open the Task Manager, the open your program, wait for 5 seconds. Look at your program process and find information "Memory Usage". Watch it closely. Then you'll see memory leak. :)

Then you basically detected the problem. Expand the code and continue putting the block code (where you doubt). Many fatal errors or (memory leak) errors can be avoided. :)
Last edited on
closed account (o3hC5Di1)
Just on a sidenote, you may want to have a quick look at this link: http://vld.codeplex.com/

All the best,
NwN
NwN wrote:
...you may want to have a quick look at this link: http://vld.codeplex.com/

That's good stuff. I'll try it out. :)
Thanks, I already read this article. I learned how to manage memory. Can I prevent leaks? How to protect code from the leak? Or is it impossible?
closed account (zb0S216C)
It's possible to prevent memory leaks by simply being careful. The example code provided by Jackson Marie intentionally (I hope) shows lack of care and logic. In general, allocating different blocks of memory is a good way to leak memory unless you utilise the use of smart pointers. However, common solutions are memory pools or garbage collection.

A memory pool is a large pre-allocated block of memory that is capable of storing any type of information. This pool of memory is normally managed by an interface which the program uses to store its data. Memory pools themselves do not leak if the pool is released. However, if an object's constructor is called, the corresponding destructor must be called.

A garbage collection system is a system that automatically frees allocated memory which saves the programmer from developing time-consuming memory management systems. A leaking GBS almost never happens.

My opinion on GBSs:
They do save the programmer time, but they don't teach proper discipline of memory like C/C++ does. Personally, I avoid GB at all costs; it's bad for my mental well-being.


Wazzak
Last edited on
> Can I prevent leaks? How to protect code from the leak? Or is it impossible?

It is very easy to prevent resource leaks - just use RAII consistently.

Not this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
my_class* bad_code( const char* cstr )
{
    my_class* pmc = new my_class( /* ... */ ) ;

    try
    {
        // call a function

        std::FILE* file = std::fopen( /* ... */ ) ;

        try
        {
            // ...
            // call a function

            char* cpy = static_cast<char*>( new char [ cstr ? 1 : std::strlen(cstr) + 1 ] ) ;
            if( cstr ) std::strcpy( cpy, cstr ) ;
            else cstr[0] = 0 ;

            try
            {
                // ...
                // call a function

                int* array = new int[100000] ;
                std::memset( array, 0, sizeof(array) ) ;

                try
                {
                    // ...
                    // call a function
                }
                catch( ... )
                {
                    delete[] array ;
                    throw ;
                }

                 delete[] array ;
             }
             catch(...)
             {
                 delete [] array ;
                 throw ;
             }
             delete [] cpy ;
        }
        catch( ... )
        {
            std::fclose(file) ;
            throw ;
        }
        std::fclose(file) ;
    }
    catch( ... )
    {
        delete pmc ;
        throw ;
    }

    return pmc ; // dump this problem on the unfortunate caller
}


But this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
std::shared_ptr<my_class> good_code( const std::string& str )
{
    std::shared_ptr<my_class> pa = std::make_shared<my_class>( /* ... */ ) ;

    // ...
    // call a function; no worries if it throws

    std::fstream file( /* ... */ ) ;

    // ...
    // call a function; no worries if it throws

    std::string cpy = str ;

    // ...
    // call a function; no worries if it throws

    std::vector<int> array(100000) ;

    // ...
    // call a function; no worries if it throws

    return pa ;
}
closed account (o3hC5Di1)
Just out of interest: When you say RAII, at present it's mostly done so by using smart pointers and STL containers as you showed right? I mean as opposed to opening a resource (or initialising a pointer) in the constructor (and providing fail safety there) and cleaning it up in the destructor?

All the best,
NwN
> Just out of interest: When you say RAII, at present it's mostly done so
> by using smart pointers and STL containers as you showed right?

Yes. The standard library also provides RAII mechanisms for other resources that it encapsulates; for example std::lock_guard and friends.


> as opposed to opening a resource (or initialising a pointer) in the constructor (and providing fail safety there)
> and cleaning it up in the destructor?

In many programs, we have to deal with resources that are not provided by the standard library. For example, there may be a database library written in C that we want to use. And it has the usual suite of sandwich functions:

1
2
3
// locks database table, returns -1 on failure
int lock_db_table( const char* table_name ) ;
void unlock_db_table( int lock_id ) ;

Now, if we use this as it is in several places, our C++ code would metamorphose into Java-like spaghetti. To avoid that, we wrap the management of the raw resource in a shim class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
struct scoped_db_table_lock
{
    explicit scoped_db_table_lock( const char* table_name ) : lock_id( lock_db_table(table_name) ) {}
    ~scoped_db_table_lock() { if( lock_id != INVALID ) unlock_db_table(lock_id) ; }

    operator bool() const { return lock_id != INVALID ; }
    bool operator! () const { return lock_id == INVALID ; }

    scoped_db_table_lock( const scoped_db_table_lock& ) = delete ;
    scoped_db_table_lock& operator= ( const scoped_db_table_lock& ) = delete ;

    scoped_db_table_lock( scoped_db_table_lock&& that ) : lock_id(that.lock_id) { that.lock_id = INVALID ; }
    scoped_db_table_lock& operator= ( scoped_db_table_lock&& that )
    {
        if( std::addressof(that) != this )
        {
            if( lock_id != INVALID ) unlock_db_table(lock_id) ;
            lock_id = that.lock_id ;
            that.lock_id = INVALID ;
        }
        return *this ;
    }

    private:
        int lock_id ;
        enum { INVALID = -1 } ;
};


Such a wrapper classes would have code that deals directly with raw resources; and they should be the only ones doing so.
closed account (o3hC5Di1)
All right, thanks very much for clearing that up :)

All the best,
NwN
Thank you Framework!!! At last I got the answer to my question!
"Yes. The standard library also provides RAII mechanisms for other resources that it encapsulates; for example std::lock_guard and friends. "
I was interested in it! Thanks for the clarification!
Thank you all! Problem solved.
Thread is closed
Topic archived. No new replies allowed.