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

Wush Wu wush978 at gmail.com
Tue Dec 30 07:41:43 CET 2014


Dear Romain, Dirk, and Qiang,

Thanks for Romain's reminder of auto appended catch block, Dirk's
explanation of leaks and exception and Qiang's simple example. Now I
understand that an uncaught exception in a c++ program might cause memory
leak. A SO Q&A (
http://stackoverflow.com/questions/27677895/valgrind-detects-errors-when-c-exception-is-not-caught)
also makes me believe that it is normal for c++ program. You are right, it
is normal for a simple C++ program.

However, I want to argue that it might be a bug for Rcpp, or Rcpp
Attributes.

For example, a package developer might use c++ exception as an error in R
because he/she believes Rcpp Attributes will transform it automatically. An
user might use the `tryCatch` in R to skip the error and keep his R process
working, so the leaking might make trouble for the user.

I verify my though by repeating the `tryCatch` block in R and the number of
lost blocks reported by valgrind is increasing. This behaviour makes me
uncomfortable since I think it is OK to pass a c++ exception to R and Rcpp
Attributes will automatically transfer the exception to R error. I think we
could solve it if the we close the c++ scope properly before raising an
error to R. That is to say, we could modify the macro VOID_END_RCPP to
avoid this error.

To verify my though, I modify the generated src/RcppExports.cpp as follow:

// test1
std::string except_message;
bool is_ex;

void test1();
RcppExport SEXP RcppMemTest_test1() {
is_ex = false;
try {
    {
        Rcpp::RNGScope __rngScope;
        test1();
    }
    return R_NilValue;
} catch( std::exception& __ex__ ){ except_message.assign(__ex__.what());
is_ex = true; }
if (is_ex) {
  forward_exception_to_r(std::logic_error(except_message));
}

Now the lost block does not increase if the `tryCatch` block in R increases.

If you agree that it is a bug, I am happy to send a pull request and we
could discuss more details there.

Best,
Wush


2014-12-30 11:32 GMT+08:00 Qiang Kou <qkou at umail.iu.edu>:

> Hi, Wush,
>
> It seems that memory leakage has nothing to do with R.
>
> Just use your code without R:
>
> #include <iostream>
> #include <stdexcept>
>
> int main(int argc, char **argv) {
>
>     std::string msg = std::string("test");
>     throw std::logic_error(msg);
>     return 0;
> }
>
> I still get the same leakage information:
>
> ==19532== Memcheck, a memory error detector
> ==19532== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
> ==19532== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for
> copyright info
> ==19532== Command: ./a.out
> ==19532==
> terminate called after throwing an instance of 'std::logic_error'
>   what():  test
> ==19532==
> ==19532== HEAP SUMMARY:
> ==19532==     in use at exit: 173 bytes in 2 blocks
> ==19532==   total heap usage: 3 allocs, 1 frees, 205 bytes allocated
> ==19532==
> ==19532== LEAK SUMMARY:
> ==19532==    definitely lost: 0 bytes in 0 blocks
> ==19532==    indirectly lost: 0 bytes in 0 blocks
> ==19532==      possibly lost: 173 bytes in 2 blocks
> ==19532==    still reachable: 0 bytes in 0 blocks
> ==19532==         suppressed: 0 bytes in 0 blocks
> ==19532== Rerun with --leak-check=full to see details of leaked memory
> ==19532==
> ==19532== For counts of detected and suppressed errors, rerun with: -v
> ==19532== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
> *Aborted (core dumped)*
>
> The program may abort before releasing the resource, so there may be
> memory leak.
>
> With try/catch, the program will exit normally. So no leakage found.
>
> Best,
>
> KK
>
>
> On Mon, Dec 29, 2014 at 10:05 PM, Dirk Eddelbuettel <edd at debian.org>
> wrote:
>
>>
>> PS  Here is a better variant that actually leaks:
>>
>> edd at max:/tmp$ cat leak.cpp
>>
>> #include <cstdio>
>> #include <cstdlib>
>> #include <iostream>
>> #include <cmath>
>>
>> int main() {
>>   double *d = new double[1024];
>>   if (d) std::cout << "Allocated" << std::endl;
>>   double e = std::exp(1.0);
>>   d = &e;
>>   exit(0);
>> }
>> edd at max:/tmp$ g++ -Wall -o leak leak.cpp
>> edd at max:/tmp$ valgrind  ./leak
>> ==16924== Memcheck, a memory error detector
>> ==16924== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
>> ==16924== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright
>> info
>> ==16924== Command: ./leak
>> ==16924==
>> Allocated
>> ==16924==
>> ==16924== HEAP SUMMARY:
>> ==16924==     in use at exit: 8,192 bytes in 1 blocks
>> ==16924==   total heap usage: 1 allocs, 0 frees, 8,192 bytes allocated
>> ==16924==
>> ==16924== LEAK SUMMARY:
>> ==16924==    definitely lost: 8,192 bytes in 1 blocks
>> ==16924==    indirectly lost: 0 bytes in 0 blocks
>> ==16924==      possibly lost: 0 bytes in 0 blocks
>> ==16924==    still reachable: 0 bytes in 0 blocks
>> ==16924==         suppressed: 0 bytes in 0 blocks
>> ==16924== Rerun with --leak-check=full to see details of leaked memory
>> ==16924==
>> ==16924== For counts of detected and suppressed errors, rerun with: -v
>> ==16924== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
>> edd at max:/tmp$
>>
>> By overwriting d the memory is lost for good, and valgrind notices as
>> you;d
>> think it would.
>>
>> Dirk
>>
>> --
>> http://dirk.eddelbuettel.com | @eddelbuettel | edd at debian.org
>> _______________________________________________
>> Rcpp-devel mailing list
>> Rcpp-devel at lists.r-forge.r-project.org
>> https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel
>>
>
>
>
> --
> Qiang Kou
> qkou at umail.iu.edu
> School of Informatics and Computing, Indiana University
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.r-forge.r-project.org/pipermail/rcpp-devel/attachments/20141230/ca26facf/attachment.html>


More information about the Rcpp-devel mailing list