Opened 4 years ago
Closed 4 years ago
#13561 closed Bugs (fixed)
boost::detail::nullary_function causes stack overflow when copied
| Reported by: | Owned by: | viboes | |
|---|---|---|---|
| Milestone: | Boost 1.69 | Component: | thread |
| Version: | Boost 1.67.0 | Severity: | Showstopper |
| Keywords: | stack, overflow, thread, future, nullary, function | Cc: |
Description
Hi,
It seems as though boost::detail::nullary_function implement a perfect forwarding constructor incorrectly, which causes a stack overflow:
Here is a simple example:
#include <boost/thread/detail/nullary_function.hpp> #include <boost/system/detail/error_code.ipp> int main(int argc, char* argv[]) { boost::detail::nullary_function<void ()> f1; auto f2 = f1; }
This ends up invoking nullary_function.hpp:81 which keeps invoking iself recursively, resulting in a stack overflow.
Change History (7)
follow-up: 2 comment:1 by , 4 years ago
comment:2 by , 4 years ago
Fix a typo in the second code block: it should be enable_if_c instead of enable_if. also this_type is nullary_function<void()> or nullary_function<R()> (depending on the specialization).
using this_type = nullary_function<void()>;
template<typename F, typename = typename boost::enable_if_c<!boost::is_same<typename decay<F>::type, this_type>::value>::type>
nullary_function(BOOST_THREAD_RV_REF(F) f):
impl(new impl_type<typename decay<F>::type>(thread_detail::decay_copy(boost::forward<F>(f))))
{}
comment:3 by , 4 years ago
| Owner: | changed from to |
|---|---|
| Status: | new → assigned |
Thanks for the report. I'll try to fix it soon but a PR on github would help as well.
comment:4 by , 4 years ago
I've some trouble identifying where there is recursion
template<typename F>
nullary_function(BOOST_THREAD_RV_REF(F) f):
impl(new impl_type<typename decay<F>::type>(thread_detail::decay_copy(boost::forward<F>(f))))
{}
impl_type is not nullary_function, isn't it?
Could you clarify?
comment:5 by , 4 years ago
Oh, I believe I see it now.
The problem is on the open overloads
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
template<typename F>
explicit nullary_function(F& f);
#endif
template<typename F>
nullary_function(BOOST_THREAD_RV_REF(F) f);
comment:6 by , 4 years ago
| Milestone: | To Be Determined → Boost 1.69 |
|---|
comment:7 by , 4 years ago
| Resolution: | → fixed |
|---|---|
| Status: | assigned → closed |
Please reopen if you believe the fix is not good enough.

From the history, it seems the bug in nullary_function has been there for a couple of years. A simple way to fix is to add another overload
nullary_function(nullary_function& other) BOOST_NOEXCEPT : impl(other.impl) { }Or to add enable_if to
template<typename F, typename = typename boost::enable_if<!boost::is_same<typename decay<F>::type, this_type>::value>::type> nullary_function(BOOST_THREAD_RV_REF(F) f): impl(new impl_type<typename decay<F>::type>(thread_detail::decay_copy(boost::forward<F>(f)))) {}