Avoid nested unwind_protect()
and unsafe string
usage
#241
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
We have taken a long hard look at manual usage of
unwind_protect()
in cpp11 and determined that it is unsafe to use it in a "nested" way. Indeed, if you were to put anRf_error()
call (imitating an R error) inside theunwind_protect()
call offill_one_ngram()
, then it causes R to crash. So once thing this PR does is remove the outerunwind_protect()
call, which wasn't actually impacting performance much.In r-lib/cpp11#327 we have some new FAQ recommendations that advise against calling
unwind_protect()
yourself at all if possible, with the one exception of character vector manipulation, as we have here.It is fairly hard to call
unwind_protect()
yourself in a safe way, you have to be careful not to violate these rules:We actually violated 2 of these here.
std::string
objects were being created inside theunwind_protect()
and those have destructors. If an R error was thrown from inside the unwind-protect, then that destructor would not be run and you'd get a memory leak. I've worked around this by moving thestd::string
declaration out of the unwind-protect, which should allow its destructor to always run.std::string
methods like the+
method can throw exceptions in rare cases. One way to avoid this is to use pure C here instead, but that is somewhat difficult, so instead I wrapped the places where exceptions were possible in a try/catch, which avoids throwing the exception across a C stack frame (which is undefined behavior). I tried manually adding inthrow std::runtime_error("oh no")
and it does indeed catch the exception safely.I am sending in a new update of cpp11 in soon. I don't think it actually breaks textrecipes, but you should probably try to get this release in sooner rather than later just to be on the safe side (since these problems are present regardless of the version of cpp11 you have)