06-14-2013 07:32 AM
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.
Solved! Go to Solution.
06-17-2013 07:44 AM - edited 06-17-2013 07:55 AM
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 ?!?
06-26-2013 07:51 AM
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
06-26-2013 07:56 AM - edited 06-26-2013 08:08 AM
[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.
06-27-2013 03:31 AM
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
06-27-2013 10:11 AM
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
06-27-2013 10:29 AM
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