Thursday, September 23, 2010

finding mem leaks with valgrind

I had been playing around with CinMonty for a couple weeks now and noticed a fairly big memory leak when I played back or rendered MPEG-PS or the AVC files from my Canon 5D(actually, H264/PCM audio). It must be stated that though I took some programming in school, I'm no C programmer. Handy with the shell, but not a C programmer. In any case, I found it interesting to try and find a memory leak in Cinelerra Monty using valgrind, a profiler/instrumenter/error detector of C programs.

Starting Valgrind
Valgrind is executed at the command line with the name of the program that valgrind will analyze. You can start valgrind with plenty of options, but I started with a few common arguments:
-check for leaks
-log to a file
-log unlimited errors

The command line looks like this:
[mule@ogre 2010_09_22]$ valgrind --leak-check=full --log-file=memLeakCinMonty.txt --error-limit=no cinelerra
Cinelerra 2.1CV
(C) 2006 Heroine Virtual Ltd.
(C) 2006-2010 The CinelerraCV Community
Internal ffmpeg 0.6+fixes
Compiled on Sat Sep 18 14:04:36 EDT 2010

Cinelerra is free software, covered by the GNU General Public License,
and you are welcome to change it and/or distribute copies of it under

certain conditions. There is absolutely no warranty for Cinelerra.
FFMPEG::init_picture failed
FFMPEG::init_picture failed
FFMPEG::init_picture failed

I'm not sure what the init_picture failed error messages are, but they occur when I playback or render MPEG-PS or H264 video. This may have something to do with the memory leak.

When running cinlerra under valgrind, the performance of Cinelerra grinds to a halt. Perhaps that's why Julian Seward (the original designer and author of Valgrind) called it valGRIND. However, performance is not so bad that you can't get usable data out of the program. For instance, valgrind shows me the following interesting overlap in memcpy:
==23140== Thread 36:

==23140== Source and destination overlap in memcpy(0x3ce5e1b0, 0x3ce7e1b0, 526848) ==23140== at 0x4A06A3A: memcpy (mc_replace_strmem.c:497)
==23140== by 0x569092: FileBase::update_pcm_history(long) (filebase.C:105)
==23140== by 0x5872F5: FileFFMPEG::read_samples(double*, long) (fileffmpeg.C:648) ==23140== by 0x56ACAA: File::read_samples(double*, long, long, float*) (file.C:1042) ==23140== by 0x500CAE: AModule::render(double*, long, int, int, int, int) (amodule.C:258)
==23140== by 0x658543: VirtualANode::read_data(double*, long, long, long) (virtualanode.C:161)

==23140== by 0x658820: VirtualANode::render_as_module(double**, double*, long, long, long) (virtualanode.C:238)
==23140== by 0x65897A: VirtualANode::render(double*, long, long, long) (virtualanode.C:178)
==23140== by 0x6576F7: VirtualAConsole::process_buffer(long, long, int, long) (virtualaconsole.C:134)
==23140== by 0x502B06: ARender::process_buffer(long, long) (arender.C:232)
==23140== by 0x502969: ARender::run() (arender.C:325)
==23140== by 0x51B4425: Thread::entrypoint(void*) (thread.C:69)

It's good that valgrind found something. Now to fix it! I've handed this info off to Monty. Hopefully he will be able to replicate my problem and fix it.
the mule

Friday, September 10, 2010

making sure opengl is available

This troubleshooting is listed in this post:

But I thought I'd repost here so that I always have this information at hand:

I have a GeForce 8800GT card installed in my box. I see glxinfo says I have OpenGL:
[sfr...@ogre my_cinelerra]$ glxinfo | head -20
name of display: :0.0
display: :0 screen: 0
direct rendering: Yes
server glx vendor string: NVIDIA Corporation
server glx version string: 1.4

I see glxgears points to the in /usr/lib64/nvidia:
[sfr...@ogre my_cinelerra]$ ldd `which glxgears` => (0x00007fff85dff000) => /usr/lib64/nvidia/ (0x00007f791fa75000) => /lib64/ (0x0000003f1bc00000) => /usr/lib64/ (0x0000003f1e800000) => /lib64/ (0x0000003f1c400000) => /lib64/ (0x0000003f1b800000) => /usr/lib64/nvidia/ (0x00007f791e5a3000) => /usr/lib64/nvidia/tls/ (0x00007f791e4a1000) => /usr/lib64/ (0x0000003f1ec00000) => /lib64/ (0x0000003f1c000000) => /usr/lib64/ (0x0000003f1e400000)
/lib64/ (0x0000003f1b400000) => /usr/lib64/ (0x0000003f1e000000

I see that the in that directory has the appropriate OpenGL hooks:
[sfr...@ogre usr]$ strings -a /usr/lib64/nvidia/ | grep glDeleteShader
[sfr...@ogre usr]$ strings -a /usr/lib64/nvidia/ | grep glUseProgram

I've tried manually pointing to the /usr/lib64/nvidia directory:
AC_CHECK_LIB([GL], [glUseProgram],
[OPENGL_LIBS="-lGL"; libGL=yes],
# On SUSE/OpenSUSE, NVidia places the OpenGL 2.0 capable library in
# but it doesn't place a there, so the linker won't pick it up
# we have to use the explicit path.
for l in /usr/lib64/nvidia /usr/X11R6/lib /usr/X11R6/lib64; do
AC_MSG_CHECKING(for glUseProgram in $l/
AC_TRY_LINK([],[extern int glUseProgram();
test $libGL = yes && break

In the end, even though ./configure did not recognize that I had openGL properly installed, I had to explicitly enable opengl on my ./configure line:
./configure --enable-opengl

Who knew?
da mule