LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

Memory leak in image rings on Linux

Solved!
Go to solution

Hello all,

I have a very serious problem I didn't have in previous version of my soft and one of the only addition I've made recently is to use image rings. The soft uses 6Mb more every minute. If I remove the rings, it stops. It could be a wrong lead, so I'm trying to write a test case, but is there a list of identified memory leaks somewhere ?

THanks.

0 Kudos
Message 1 of 7
(4,691 Views)

OK guys, there's a very serious leak on Linux, confirmed by the code below. Every time you change the value of a picture ring, either by clicking on the arrow of the picture ring or right-click on it (callback to SetCtrlVal), it uses 1 extra Mb of mem for a 512x512 pixel image !!!

Here's a sample code:

// Right-click the ring to cause memory leak

#include <stdio.h>
#include <stdlib.h>
#include <cvirte.h>
#include <userint.h>

#define RND_COLOR (((rand()<<16) ^ (rand()<<8) ^ rand()) & 0xFFFFFF)
// (int)((double)(0xFFFFFF)*rand()/RAND_MAX)

static int Pnl=0,
	Text, Ring,				// Controls
	NbVals=16,				// Number of images in the ring
	Width=512, Height=512;	// Of the Canvas and image ring

// Returns memory used by process in 4Kb page:
// TotalSize Resident Share Text Lib Data Dirty
// See "man proc" section statm
static char* ReadOffMemoryStatus(void) {
	static char statm[80];
	statm[0]='\0';
#ifdef _NI_linux_
	FILE *f = fopen("/proc/self/statm","r");
	if (f) 
		fgets (statm, 79, f),
		fclose(f);
#endif
	return statm;
}

static void Prepare(const int Nb) {
	Point polyPoints[10]={{0,0}};
	char Str[10];
	int i, Bitmap;
	int Canvas=NewCtrl(Pnl, CTRL_CANVAS, "", 0, 0);
	SetCtrlAttribute(Pnl, Canvas, ATTR_DRAW_POLICY, VAL_UPDATE_IMMEDIATELY);
	SetCtrlAttribute(Pnl, Canvas, ATTR_WIDTH,  Width);
	SetCtrlAttribute(Pnl, Canvas, ATTR_HEIGHT, Height);
//	SetCtrlAttribute(Pnl, Canvas, ATTR_ENABLE_ANTI_ALIASING, 1);	// No compile on Linux
	SetCtrlAttribute(Pnl, Canvas, ATTR_PICT_BGCOLOR,   RND_COLOR /*VAL_TRANSPARENT*/);
	SetCtrlAttribute(Pnl, Canvas, ATTR_PEN_FILL_COLOR, RND_COLOR);
	SetCtrlAttribute(Pnl, Canvas, ATTR_PEN_COLOR,      RND_COLOR);
	SetCtrlAttribute(Pnl, Canvas, ATTR_PEN_WIDTH, 7);
	for (i=0; i<10; i++)
		polyPoints[i].x=(Width*rand()/RAND_MAX),
		polyPoints[i].y=(Height*rand()/RAND_MAX);
	
	sprintf(Str, "%d", Nb);
//	CanvasStartBatchDraw(Pnl, Canvas);
	
	// This sometimes doesn't work on Linux
	CanvasDrawPoly (Pnl, Canvas, 10, polyPoints, 1, VAL_DRAW_FRAME_AND_INTERIOR);
	
	CanvasDrawLine (Pnl, Canvas, MakePoint(Width-1,0), MakePoint(0, Height-1));

	SetCtrlAttribute(Pnl, Canvas, ATTR_PEN_COLOR,      VAL_BLACK);
	SetCtrlAttribute(Pnl, Canvas, ATTR_PEN_FILL_COLOR, VAL_WHITE);
	CanvasDrawText(Pnl, Canvas, Str, VAL_APP_META_FONT,
					MakeRect (2, 2, VAL_KEEP_SAME_SIZE, VAL_KEEP_SAME_SIZE), VAL_UPPER_LEFT);
//	CanvasEndBatchDraw(Pnl, Canvas);
	GetCtrlBitmap(Pnl, Canvas, 0, &Bitmap);
	DiscardCtrl  (Pnl, Canvas);
	InsertListItem(Pnl, Ring, Nb, NULL, Nb);	// The value is the color, so remember which one you use
	SetCtrlBitmap (Pnl, Ring, Nb, Bitmap);
	DiscardBitmap (Bitmap);
}

int CVICALLBACK cb_Change(int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2) {
	static int i=0;
	switch (event) {
		case EVENT_RIGHT_CLICK:
		case EVENT_RIGHT_DOUBLE_CLICK:
			SetCtrlVal(Pnl, Ring, i=(i+1)%NbVals);
			// No break;
		case EVENT_COMMIT:
			SetCtrlVal(Pnl, Text, ReadOffMemoryStatus());
			break;
	}
	return 0;
}

int CVICALLBACK cb_Quit(int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2) {
	switch (event) {
		case EVENT_COMMIT: QuitUserInterface (0); break;
	}
	return 0;
}

int main (int argc, char *argv[]) {
	int i, Quit;
	if (InitCVIRTE (0, argv, 0) == 0) return -1;
	
	Pnl = NewPanel (0, "Test image ring", 20, 20, Height+20, Width);
	Text = NewCtrl (Pnl, CTRL_STRING_LS, "Memory use (in 4Kb pages)", 0, 0);
	Ring = NewCtrl (Pnl, CTRL_PICTURE_RING, "", 20, 0);
	Quit = NewCtrl (Pnl, CTRL_SQUARE_BUTTON_LS, "", 50, 50);

	SetCtrlAttribute(Pnl, Ring, ATTR_HEIGHT, Height);
	SetCtrlAttribute(Pnl, Ring, ATTR_WIDTH,  Width);
	SetCtrlAttribute (Pnl, Ring, ATTR_CTRL_MODE, VAL_HOT);
	SetCtrlAttribute(Pnl, Ring, ATTR_CALLBACK_FUNCTION_POINTER, cb_Change);
	for (i=0; i<NbVals; i++) Prepare(i);
	
	SetCtrlAttribute(Pnl, Text, ATTR_WIDTH, 250);
	SetCtrlAttribute(Pnl, Text, ATTR_LABEL_LEFT, 250);
	SetCtrlAttribute(Pnl, Text, ATTR_LABEL_TOP, 0);
	
	SetCtrlAttribute(Pnl, Quit, ATTR_CALLBACK_FUNCTION_POINTER, cb_Quit);
	SetCtrlAttribute(Pnl, Quit, ATTR_VISIBLE, 0);
	SetCtrlAttribute(Pnl, Quit, ATTR_SHORTCUT_KEY, VAL_ESC_VKEY);
	SetPanelAttribute(Pnl, ATTR_CLOSE_CTRL, Quit);

	DisplayPanel (Pnl);
	
	RunUserInterface ();
	return 0;
}

 

There are other issues as well:

 - CanvasDrawPoly sometimes doesn't work.

 - The anti-aliasing on a canvas doesn't compile.

 

Is there anything more recent than CVI 2010 for Linux ?!?

 

0 Kudos
Message 2 of 7
(4,669 Views)
Solution
Accepted by topic author gdargaud

Hello Guillaume,

 

I've investigated this and confirmed what you are seeing. There is indeed a very serious leak in the Linux module. I'm really sorry for the inconvenience this has caused you. We've created an internal bug reported for this issue (414435) and it will be fixed soon.

 

To answer your last question, there isn't yet a more recent Linux version than 2010, but there will be an update to the Linux module later this year, and it will include this fix.

 

I haven't yet investigated the issue with CanvasDrawPoly, but I'll do that soon.

 

The error with anti-aliasing is expected since that feature was added in 2012.

 

Luis

0 Kudos
Message 3 of 7
(4,601 Views)

[Our messages crossed path within a few minutes]

 

Thanks for the confirmation. I'm using a stack of picture controls as a workaround. So, any deadline on the next Linux CVI version ?

 

Please, please, make sure that the next release fixes the 'plot area' bug #344028 which has been making my life miserable.

0 Kudos
Message 4 of 7
(4,598 Views)

Yes, it will definitely include a fix for that bug.

 

Unfortunately, I can't be as specific as you'd like me to be with respect to the release date. I can say with high confidence that it will be released in 2013. If it looks to you like it's taking too long, please don't hesitate to ask about the status here in the forum. I still won't be able to give you an exact date, but as we get closer, my confidence will increase, and I should be able to be more specific than I'm being now.

 

Luis

0 Kudos
Message 5 of 7
(4,572 Views)

HI Guillaume,

 

I've now looked at the CanvasDrawPoly issue and it doesn't look like there is a bug. I confirmed that the program that you listed in the post is in fact not drawing polygons correctly (in Linux only) but I think it's for a legitimate reason. The problem that I'm seeing is that the polygon that is being passed to the CanvasDrawPoly function is filled with zeros and the reason for this, as best as I can tell, comes from this code from the Prepare function:

 

    polyPoints[i].x=(Width*rand()/RAND_MAX);
    polyPoints[i].y=(Height*rand()/RAND_MAX);

 

In Linux, RAND_MAX is much larger than it is in Windows. Consequently, the values returned by the rand() function are also much larger. The rand() function returns a 32-bit integer, and the Width and Height variables in your program are also 32-bit integers. When the value returned by rand() is fairly large, the multiplication causes a 32-bit integer overflow. When this happens, the ensuing division returns 0.

 

You could fix this fairly easily by up-casting one of the operands:

 

    polyPoints[i].x=((long long)Width*rand()/RAND_MAX);
    polyPoints[i].y=((long long)Height*rand()/RAND_MAX);


Luis

0 Kudos
Message 6 of 7
(4,554 Views)

Hah, my bad. I've been bitten by this 'feature' before and I should have known better. I still wonder why there isn't a float random in a range in C.

Thanks

0 Kudos
Message 7 of 7
(4,549 Views)