[Newbie] Memory leak when writing to file

L

Lars

Hello all,

My program seems to suffer from some sort of memory leak problem that
I'm having trouble fixing. The background is as follows: I'm writing a
program that reads data from a socket. I then want to display the
values in a real-time diagram and write the values in a text file
along with a timestamp.

I'm experimenting in C and using XLib and I've managed to put together
a running program that reads, displays and logs data. It also handles
events (pressed keys), so that I can start and stop logging to file.

The program behaves well, except when I start logging. I use vmstat to
monitor memory usage and I see that the memory usage is constant when
I'm not logging to file, but it immediately starts to increase and
continues to do so for as long as I'm writing to file.

The program runs a loop that reads data and handles it (I've shortened
it somewhat):

int mainloop()
{
while( 1 ) {

while(!is_connected) {
printf("Not connected.\n");
establish_connection(servIP);
}

/*
* When connected, we need data within 4 seconds, otherwise we
consider
* the server to be dead. So we set the alarm(3L);
*/

alarm(3L);

/* Wait for data from the server */
if (( (bytesRcvd = recv(sock, echoBuffer, RCVBUFSIZE - 1, 0)) <=
0)
&& is_connected==1 ) {
echoBuffer[bytesRcvd] = '\0'; /* Terminate the string! */
}


/*
* Since we got to this line, we have received something
* from the server.
*/
alarm(0); /* So we reset the alarm. */

echoBuffer[bytesRcvd] = '\0';
cpuValue = 100 - atoi(echoBuffer);

/*
* Check to see if logging is ON and if so, write value to file.
*/

// THIS IF-BLOCK IS THE CODE I'M MOST CONCERNED ABOUT

if(logging_on) {
seconds = time(NULL);
sprintf(fileString, "%i\t%d\n", seconds, 100 - cpuValue);
fputs(fileString, file);
fflush(file);
}

/*
* Goes through the drawing procedure;
*/
clearArea();
drawGridLines();
drawText();
plot_cpu_value();
XFlush(display); // No sure if necessary.


/*
* Checks for any Events, such as mouse clicks or button presses.
*/

if(XPending(display)) {

XNextEvent( display, &event );

switch( event.type ) {
/*
* Handle pressed keys.
*/
case KeyPress:
i = XLookupString( &event, text, 10, &key, 0 );

if ( i == 1 && text[0] == 'q' ) {
if(logging_on == 1) {
printf("Closing file");
fclose(file);
}
printf("Terminated normally.\n");
exit(0);
}

if ( i == 1 && text[0] == 'h' ) {
show_help();
}

// If I'm not already logging, I open a file
// and set logging_on = 1. If I AM already logging
// I close the open file and set logging_on = 0;

if ( i == 1 && text[0] == 's' ) {
if(logging_on == 0) {
file = fopen(file_name, "a");
if(setvbuf(file, NULL, _IONBF, 0)) {
printf("Bad setvbuf\n");
exit(1);
}
if(file == NULL) {
printf("Error: can't create file,\n");
} else {
printf("Good to go. Logging.\n");
logging_on = 1;
}
} else {
printf("Now closing file...\n");
fclose(file);
logging_on = 0;
}
}
break;
}
}
}
}


I've tried to narrow down the problem in several ways.

1) It doesn't matter if I actually read anything from the socket or if
I comment that out and explicitly set cpuValue = 5 in every loop.

2) It doesn't matter if I comment out the drawing procedures:

clearArea();
drawGridLines();
drawText();
plot_cpu_value();
XFlush(display);

3) However, it DOES matter what I write to the file. If I comment out
the part where I write the value and timestamp:

// seconds = time(NULL);
// sprintf(fileString, "%i\t%d\n", seconds, 100 - cpuValue);
// fputs(fileString, file);

and replace this with writing a constant string such as:

fputs("test", file);

It seems that the longer the string I want to write is, the faster the
memory drains away.

I've tried playing with setvbuf() without noticing any difference.
fflush() or no fflush() doesn't seem to make a difference either.

I would really appreciate any help you have to offer on how to stop
this behavour!

Thank you for your time and help,
Lars
 
J

Jens.Toerring

Lars said:
My program seems to suffer from some sort of memory leak problem that
I'm having trouble fixing. The background is as follows: I'm writing a
program that reads data from a socket. I then want to display the
values in a real-time diagram and write the values in a text file
along with a timestamp.
The program behaves well, except when I start logging. I use vmstat to
monitor memory usage and I see that the memory usage is constant when
I'm not logging to file, but it immediately starts to increase and
continues to do so for as long as I'm writing to file.

Your program is so full of platform specific calls that it's
rather off-topic here. Moreover, you're leaving out lots of
important bits. It probably would be better to ask that in
a group that is dealing with kind of platform you're writing
that for, probably comp.unix.programmer would fit. And then
post something complete, i.e. something that has all the
variable definitions still in and can be compiled.

<OT>
Many systems use buffers for files instead of writing stuff to the
disk immediately. Since you don't say what numbers you're looking
at with your memory monitor I have no idea if that could be the
reason for what you are seeing.
The program runs a loop that reads data and handles it (I've shortened
it somewhat):
int mainloop()
{
while( 1 ) {
while(!is_connected) {
printf("Not connected.\n");
establish_connection(servIP);
}

Shouldn't you now set is_connected?
/*
* When connected, we need data within 4 seconds, otherwise we
consider
* the server to be dead. So we set the alarm(3L);
*/
alarm(3L);

/* Wait for data from the server */
if (( (bytesRcvd = recv(sock, echoBuffer, RCVBUFSIZE - 1, 0)) <=
0)
&& is_connected==1 ) {
echoBuffer[bytesRcvd] = '\0'; /* Terminate the string! */

If the bytesRcvd is less than 0 you definitely don't want to use
that number as the index into the echoBuffer. And none of your
variables is defined anywhere, so I can only hope that the
echoBuffer is either an array large enough or a pointer to
a large enough memory area you own.
}

/*
* Since we got to this line, we have received something
* from the server.
*/
alarm(0); /* So we reset the alarm. */

echoBuffer[bytesRcvd] = '\0';

Same problem here - you can end up here with bytesRcvd being
less than 0 (at least as far as you show the code of your
program). And for all I can see, if the alarm() signal arrived
bytesRcvd has an unitinitialized value.
cpuValue = 100 - atoi(echoBuffer);

Since you can't reasonably check if atoi() failed you better use
strtol(), which allows error checking.
/*
* Check to see if logging is ON and if so, write value to file.
*/
// THIS IF-BLOCK IS THE CODE I'M MOST CONCERNED ABOUT
if(logging_on) {

I hope you initialized loggin_on somewhere to 0.
seconds = time(NULL);

time() returns a value of type time_t. There's no guarantee
that it is an integer (unless your system makes such a
promise).
sprintf(fileString, "%i\t%d\n", seconds, 100 - cpuValue);

What's fileString? There's no definition I can see and it might
just be a pointer pointing to some random location in memory for
all I know. And why do you first have

cpuValue = 100 - atoi( echoBuffer );

and now print out

100 - cpuValue

Wouldn't it be simpler to just have

cpuValue = atoi( echoBuffer );

and then print that out (or maybe echoBuffer itself)?

fputs(fileString, file);
fflush(file);
}

Nothing looks really fishy (in the sense that it would easily
explain a memory leak) here. But perhaps you're showing us
not the important parts. It might be that e.g. fileString
is a global char pointer variable for which you allocate
memory each time through the loop but forget to deallocate the
memory afterwards. That would be a classic example of a memory
leak but if that's the case is impossible to say.

All the rest doesn't seem to have any influence and is mostly
platform specific. And simply doesn't make too much sense
speculating what could go wrong when the code you show is
that castrated that one is reduced to mere speculations.
3) However, it DOES matter what I write to the file. If I comment out
the part where I write the value and timestamp:
// seconds = time(NULL);
// sprintf(fileString, "%i\t%d\n", seconds, 100 - cpuValue);
// fputs(fileString, file);
and replace this with writing a constant string such as:
fputs("test", file);
It seems that the longer the string I want to write is, the faster the
memory drains away.

Looks to me like a typical example of an OS that doesn't write
out buffers to disk immediately but keeps them in memory as
long as possible. But if that's the case or if you have a
memory leak is impossible to find out from the code you
posted.
Regards, Jens
 
A

Alan Balmer

On 13 Aug 2004 07:45:52 -0700, (e-mail address removed) (Lars) wrote:

<OT>
Is this HP-UX, by any chance? If so, try specifying a buffer for your
file open/write/close operation (in the setvbuf). If it makes a
difference, I'll tell you why ;-)
</OT>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,531
Members
45,004
Latest member
KetoBoostGummies

Latest Threads

Top