<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Oct 3, 2014, at 14:50, David Blaikie <<a href="mailto:dblaikie@gmail.com" class="">dblaikie@gmail.com</a>> wrote:</div><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote">On Fri, Oct 3, 2014 at 12:55 PM, Jared Grubb <span dir="ltr" class=""><<a href="mailto:jared.grubb@gmail.com" target="_blank" class="">jared.grubb@gmail.com</a>></span> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><div class="">I spoke with Marshall briefly about this at CppCon. My suggestion is that std::function should either:</div><div class=""> * correctly capture blocks and just work (as this patch does)</div><div class=""> * compile with error if you try it (and also maybe add a convenience adaptor like you suggest to allow it to manually work)</div><div class=""><br class=""></div><div class="">The current problem is that if you write something like this:</div><div class=""> template <typename F> doSomething(F&& functor) { std::function<...> capturing = std::forward<F>(functor); ... }</div><div class="">This works great for lambdas. For blocks, it compiles just fine but has runtime issues.</div></div></blockquote><div class=""><br class=""></div><div class="">What runtime issues are you referring to? Could you provide a simple standalone complete example?</div></div></div></div></div></blockquote><div><br class=""></div><div><div><div><div>Here's an example.</div><div><br class=""></div></div></div><blockquote style="margin: 0px 0px 0px 40px; border: none; padding: 0px;" class=""><div><div><div><div><div><div><div>int main(int argc, const char**) {</div><div> std::function<void()> f;</div><div><br class=""></div><div><div> std::vector<int> vec = {1, 2, 3};</div><div> if (argc == 1) {</div><div> f = ^{ std::cout << vec.size() << " (block)\n"; };</div><div> } else {</div><div> f = [=]{ std::cout << vec.size() << " (lambda)\n"; };</div><div> }</div><div><br class=""></div></div><div> f();</div><div>}</div><div><br class=""></div></div></div></div></div></div></div></blockquote><div>On my machine, it doesnt crash, but the block part is definitely broken:</div><div>$ ./a.out</div><div><div>0 (block)</div><div>$ ./a.out 1</div><div>3 (lambda)</div><div><br class=""></div><div>Other examples, especially multithreaded ones, will crash and behave in undefined ways.</div><div><br class=""></div></div><div><blockquote type="cite" class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class="">I assume the issue is that std::function will capture the block's (presumably raw) pointer by value but do none of the increment/decrement.</div></div></div></div></blockquote><div><br class=""></div><div>Yes.</div><br class=""><blockquote type="cite" class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class="">This doesn't seem necessarily broken & I'm not sure (for myself) it merits library support to protect.</div></div></div></div></blockquote><blockquote type="cite" class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class=""><br class="">This would be the same behavior as any other lifetime issues with pointer captures.<br class=""><br class=""> std::function<...> func() {<br class=""> int i;<br class=""> int *j = &i;<br class=""> return [=j] () { ... }; // captured j by value, but it points to something that goes out of scope at the end of the function. Bad.<br class=""> }<br class=""><br class="">But similar code isn't a problem at all:<br class=""><br class=""></div><div class=""> void func(std::function<...>); // func calls the std::function, maybe copies it around, but doesn't copy it to global storage/anywhere that outlives the <br class=""> ...<br class=""> int i;<br class=""> int *j = &i;<br class=""> func([=j]() { ... });<br class=""></div></div></div></div></blockquote><div><br class=""></div><div>You're right that it's the same "bad pointer to stack" issue, but the problem is at a different level. In the example above, the closures themselves are perfectly fine. The problem is that std::function captures the closure incorrectly. That's why I think it's a library issue.</div><div><br class=""></div><div>Jared</div></div></div><div><br class=""></div></div></body></html>