[Rcpp-devel] Does uncaught c++ exception cause memory leak?

Dirk Eddelbuettel edd at debian.org
Tue Dec 30 03:48:50 CET 2014


Hi Wush,

On 30 December 2014 at 01:28, Wush Wu wrote:
| I have a question which is described in the subject.

Yes it can.

Which is why some C++ coding guidelines prohibit use of exception. Also,
Meyers has some good explanations of why you can never throw in destructor:
exceptions could get in the way.  

| It is discovered when I use the valgrind to check my package.
| 
| Because I am not familiar with valgrind, please help me verify that if this is
| a bug of Rcpp or not.
| 
| Here is a minimal reproducible example with docker and the log of valgrind:
| 
| https://gist.github.com/wush978/629743109e4aaa762968

That is a pretty standard use case. You don't even need Docker for this: the
rocker r-base image uses the same R binary you'd get in Debian or Ubuntu.

What I sometimes find useful when I need to remind myself about how valgrind
works (and do see the "Writing R Extensions" manual which has some a few good
tips, including useful options) is to use a really simple test to reconfirm
findings.  Consider eg this program

    edd at max:/tmp$ cat leak.cpp                                                                                                                                                                                           
    
    #include <cstdio>
    #include <cstdlib>
    #include <iostream>
    
    int main() {
      double *d = new double[1024];
      if (d) std::cout << "Allocated" << std::endl;
      exit(0);
    }

Obviously, we stick memory onto *d and never release it. It looks like
classic old C code with all its traps. It should show up as a leak. 

Does it?  Well yes -- compile and run:

    edd at max:/tmp$ g++ -Wall -o leak leak.cpp 
    edd at max:/tmp$ valgrind  ./leak                                                                                                                                                                                       
    ==10545== Memcheck, a memory error detector
    ==10545== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
    ==10545== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
    ==10545== Command: ./leak
    ==10545== 
    Allocated
    ==10545== 
    ==10545== HEAP SUMMARY:
    ==10545==     in use at exit: 8,192 bytes in 1 blocks
    ==10545==   total heap usage: 1 allocs, 0 frees, 8,192 bytes allocated
    ==10545== 
    ==10545== LEAK SUMMARY:
    ==10545==    definitely lost: 0 bytes in 0 blocks
    ==10545==    indirectly lost: 0 bytes in 0 blocks
    ==10545==      possibly lost: 0 bytes in 0 blocks
    ==10545==    still reachable: 8,192 bytes in 1 blocks
    ==10545==         suppressed: 0 bytes in 0 blocks
    ==10545== Rerun with --leak-check=full to see details of leaked memory
    ==10545== 
    ==10545== For counts of detected and suppressed errors, rerun with: -v
    ==10545== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
    edd at max:/tmp$ 

and lo and behold the 8 bytes per double time 1024 elements are the ones
found here.

You can play around creating simple examples involving exceptions -- but as a
general rule "yes, exceptions can leak" as there is no magic trick to
suppress it.  

"Normally" you are guaranteed constructor and destructor and the beginning
and end of scope.  Exceptions change that.  How to deal with that is somewhat
complicated.  

Dirk

-- 
http://dirk.eddelbuettel.com | @eddelbuettel | edd at debian.org


More information about the Rcpp-devel mailing list