Bardai
Bardai

Reputation: 3

Memory usage of C++ program grows, (shown in Debian's "top"), until it crashes

I'm working on a C++ program that should be able to run for several days, so it is a bit of a hassle that its memory consumption seems to grow really fast.

The full code of the program is a little long, so I'll post just the related things. The structure is the following:

int main (void){
//initialization of the global variables
error = 0;
state = 0;
cycle = 0;
exportcycle = 0;
status = 0;
counter_temp_ctrl = 0;
start = 0;
stop = 0;


inittimer();
mysql_del ("TempMeas");
mysql_del ("TempMeasHist");
mysql_del ("MyControl");
mysql_del ("MyStatus");
initmysql();



while(1){

    statemachine();

    pause();

    }

}

The timer function that is initialized above is the following:

void catch_alarm (int sig)
{
//Set the statemachine to state 1 (reading in new values)

    start = readmysql("MyStatus", "Start", 0);
    stop = readmysql("MyStatus", "Stop", 0);

       if (start == 1){
            state = 1;
      }
      if (stop == 1){
            state = 5;
      }


  //printf("Alarm event\n");
  signal (sig, catch_alarm);

  return void();
}

So basically, since I'm not setting the start bit in the webinterface that modifies the MyStatus Tab the program just calls the readmysql function twice every second (the timer's interval). The readmysql function is given below:

float readmysql(string table, string row, int lastvalue){
float readdata = 0;

// Initialize a connection to MySQL
MYSQL_RES *mysql_res;
MYSQL_ROW mysqlrow;
MYSQL *con = mysql_init(NULL);
if(con == NULL)
{
error_exit(con);
}


if (mysql_real_connect(con, "localhost", "user1", "user1", "TempDB", 0, NULL, 0) == NULL)
{
error_exit(con);
}

if (lastvalue == 1){
    string qu = "Select "+ row +" from "+ table +" AS a where MeasTime=(select MAX(MeasTime) from "+ table;
    error = mysql_query(con, qu.c_str());
}
else{
    string qu = "Select "+ row +" from "+ table;
    error = mysql_query(con, qu.c_str());
}


mysql_res = mysql_store_result(con);

while((mysqlrow = mysql_fetch_row(mysql_res)) != NULL)
{
    readdata = atoi(mysqlrow[0]);
}

//cout << "readdata "+table+ " "+row+" = " << readdata << endl;

// Close the MySQL connection
mysql_close(con);

//delete mysql_res;
//delete mysqlrow;


return readdata;
}

I thought that the variables in this function are stored on the stack and are freed automaticaly when leaving the function. However it seems that some part of the memory is not freed, because it just grows after all. As you can see I have tried to use the delete function on two of the variables. Seems to have no effect. What am i doing wrong in terms of memory-management and so on?

Thanks for your help!

Greetings Oliver.

Upvotes: 0

Views: 212

Answers (2)

uml&#228;ute
uml&#228;ute

Reputation: 31284

If your program continuously consumes memory (without ever releasing it), then you have a memory leak.

A good way to detect memory leaks, is to run it through a memory debugger, e.g. valgrind:

$ valgrind /path/to/my/program

Once your program started eating memory, stop it and valgrind will give you a nice summary about where your program allocated memory that was never freed.

There is no need to let the system run out of memory and crash; just wait until it has eaten some memory that has not been freed. Then fix your code. Then repeat until no more memory errors can be detected.

Also note that valgrind intercepts your systems memory management. This usually results in a (severe) performance penalty.

Upvotes: 0

KIIV
KIIV

Reputation: 3739

At least mysql_store_result is leaking. From documentation:

After invoking mysql_query() or mysql_real_query(), you must call mysql_store_result() or mysql_use_result() for every statement that successfully produces a result set (SELECT, SHOW, DESCRIBE, EXPLAIN, CHECK TABLE, and so forth). You must also call mysql_free_result() after you are done with the result set.

Upvotes: 3

Related Questions