<div dir="ltr"><div><div><div><div><div>Dear Romain, Dirk, and Qiang,<br></div><div><br>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 (<a href="http://stackoverflow.com/questions/27677895/valgrind-detects-errors-when-c-exception-is-not-caught">http://stackoverflow.com/questions/27677895/valgrind-detects-errors-when-c-exception-is-not-caught</a>) also makes me believe that it is normal for c++ program. You are right, it is normal for a simple C++ program.<br></div><br></div>However, I want to argue that it might be a bug for Rcpp, or Rcpp Attributes.<br><br></div>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.<br><br></div><div>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.<br><br></div></div><div></div>To verify my though, I modify the generated src/RcppExports.cpp as follow:<br><br>// test1<br>std::string except_message;<br>bool is_ex;<br><br>void test1();<br>RcppExport SEXP RcppMemTest_test1() {<br>is_ex = false;<br>try {<br>    {<br>        Rcpp::RNGScope __rngScope;<br>        test1();<br>    }<br>    return R_NilValue;<br>} catch( std::exception& __ex__ ){ except_message.assign(__ex__.what()); is_ex = true; }<br>if (is_ex) {<br>  forward_exception_to_r(std::logic_error(except_message));<br>}<br><br><div>Now the lost block does not increase if the `tryCatch` block in R increases.<br><br></div><div>If you agree that it is a bug, I am happy to send a pull request and we could discuss more details there.<br><br></div><div>Best,<br></div><div>Wush<br></div><div><div><div><div><div><div><div><div><div><br></div></div></div></div></div></div></div></div></div></div><div class="gmail_extra"><br><div class="gmail_quote">2014-12-30 11:32 GMT+08:00 Qiang Kou <span dir="ltr"><<a href="mailto:qkou@umail.iu.edu" target="_blank">qkou@umail.iu.edu</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Hi, Wush,<div><br></div><div>It seems that memory leakage has nothing to do with R.</div><div><br></div><div>Just use your code without R:</div><div><br></div><div><div>#include <iostream></div><div>#include <stdexcept></div><div><br></div><div>int main(int argc, char **argv) {</div><div><br></div><div>    std::string msg = std::string("test");</div><div>    throw std::logic_error(msg);</div><div>    return 0;</div><div>}</div></div><div><br></div><div>I still get the same leakage information:</div><div><br></div><div><div>==19532== Memcheck, a memory error detector</div><div>==19532== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.</div><div>==19532== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info</div><div>==19532== Command: ./a.out</div><div>==19532== </div><div>terminate called after throwing an instance of 'std::logic_error'</div><div>  what():  test</div><div>==19532== </div><div>==19532== HEAP SUMMARY:</div><div>==19532==     in use at exit: 173 bytes in 2 blocks</div><div>==19532==   total heap usage: 3 allocs, 1 frees, 205 bytes allocated</div><div>==19532== </div><div>==19532== LEAK SUMMARY:</div><div>==19532==    definitely lost: 0 bytes in 0 blocks</div><div>==19532==    indirectly lost: 0 bytes in 0 blocks</div><div>==19532==      possibly lost: 173 bytes in 2 blocks</div><div>==19532==    still reachable: 0 bytes in 0 blocks</div><div>==19532==         suppressed: 0 bytes in 0 blocks</div><div>==19532== Rerun with --leak-check=full to see details of leaked memory</div><div>==19532== </div><div>==19532== For counts of detected and suppressed errors, rerun with: -v</div><div>==19532== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)</div><div><b>Aborted (core dumped)</b></div></div><div><br></div><div>The program may abort before releasing the resource, so there may be memory leak.</div><div><br></div><div>With try/catch, the program will exit normally. So no leakage found.</div><div><br></div><div>Best,</div><div><br></div><div>KK</div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote"><div><div class="h5">On Mon, Dec 29, 2014 at 10:05 PM, Dirk Eddelbuettel <span dir="ltr"><<a href="mailto:edd@debian.org" target="_blank">edd@debian.org</a>></span> wrote:<br></div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="h5"><br>
PS  Here is a better variant that actually leaks:<br>
<span><br>
edd@max:/tmp$ cat leak.cpp<br>
<br>
#include <cstdio><br>
#include <cstdlib><br>
#include <iostream><br>
</span>#include <cmath><br>
<span><br>
int main() {<br>
  double *d = new double[1024];<br>
  if (d) std::cout << "Allocated" << std::endl;<br>
</span>  double e = std::exp(1.0);<br>
  d = &e;<br>
  exit(0);<br>
<span>}<br>
edd@max:/tmp$ g++ -Wall -o leak leak.cpp<br>
edd@max:/tmp$ valgrind  ./leak<br>
</span>==16924== Memcheck, a memory error detector<br>
==16924== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.<br>
==16924== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info<br>
==16924== Command: ./leak<br>
==16924==<br>
Allocated<br>
==16924==<br>
==16924== HEAP SUMMARY:<br>
==16924==     in use at exit: 8,192 bytes in 1 blocks<br>
==16924==   total heap usage: 1 allocs, 0 frees, 8,192 bytes allocated<br>
==16924==<br>
==16924== LEAK SUMMARY:<br>
==16924==    definitely lost: 8,192 bytes in 1 blocks<br>
==16924==    indirectly lost: 0 bytes in 0 blocks<br>
==16924==      possibly lost: 0 bytes in 0 blocks<br>
==16924==    still reachable: 0 bytes in 0 blocks<br>
==16924==         suppressed: 0 bytes in 0 blocks<br>
==16924== Rerun with --leak-check=full to see details of leaked memory<br>
==16924==<br>
==16924== For counts of detected and suppressed errors, rerun with: -v<br>
==16924== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)<br>
edd@max:/tmp$<br>
<br>
By overwriting d the memory is lost for good, and valgrind notices as you;d<br>
think it would.<br>
<span><br>
Dirk<br>
<br>
--<br>
<a href="http://dirk.eddelbuettel.com" target="_blank">http://dirk.eddelbuettel.com</a> | @eddelbuettel | <a href="mailto:edd@debian.org" target="_blank">edd@debian.org</a><br>
</span></div></div><span class=""><div><div>_______________________________________________<br>
Rcpp-devel mailing list<br>
<a href="mailto:Rcpp-devel@lists.r-forge.r-project.org" target="_blank">Rcpp-devel@lists.r-forge.r-project.org</a><br>
<a href="https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel" target="_blank">https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel</a><br>
</div></div></span></blockquote></div><span class="HOEnZb"><font color="#888888"><br><br clear="all"><div><br></div>-- <br><div><div dir="ltr">Qiang Kou<div><a href="mailto:qkou@umail.iu.edu" target="_blank">qkou@umail.iu.edu</a><br><div>School of Informatics and Computing, Indiana University</div><div><br></div></div></div></div>
</font></span></div>
</blockquote></div><br></div>