Created attachment 34289 [details] Preprocessed source I believe the program below is valid and correct, but I see heap corruption at the end of main() (in std::map::~map) when I allow the compiler to deduce return type of the lambda. Both the parameters to apply() are still alive when the returned lambda is invoked, so fn(arg) should safely return a valid const ref to a tuple. If the return type for the lambda is given explicitly (see comments in code) then everything is fine, whether it's returning by value or by const ref. Compiling with "-Wall --std=c++11 -O0 -g3"; optimisation level seems to make no difference. ---------------------------------------------------------------- #include <functional> #include <map> #include <string> #include <tuple> typedef std::tuple<std::string, std::string, double> Result; typedef std::map<int, Result> Argument; typedef std::function<const Result & (const Argument &)> Function; std::function<Result ()> apply (const Argument &arg, const Function &fn) { // No trouble with any of these... // return [&fn, &arg]() -> Result { return fn(arg); }; // return [&fn, &arg]() -> const Result & { return fn(arg); }; // return [&fn, &arg]() { Result r = fn(arg); return r; }; // But this causes heap corruption return [&fn, &arg]() { return fn(arg); }; } const Result &func (const Argument &arg) { // std::map::at returns a const ref return arg.at(0); } int main (int argc, char *argv[]) { Argument arg; arg[0] = Result("", "a", 0); Function f = &func; auto g = apply(arg, f); g(); return 0; } ---------------------------------------------------------------- Using built-in specs. COLLECT_GCC=/software/thirdparty/gcc/4.9.1-0.el6_64/bin/g++ COLLECT_LTO_WRAPPER=/software/thirdparty/gcc/4.9.1-0.el6_64/libexec/gcc/x86_64-unknown-linux-gnu/4.9.1/lto-wrapper Target: x86_64-unknown-linux-gnu Configured with: ../configure --prefix=/software/thirdparty/gcc/4.9.1-0.el6_64 --with-system-zlib --enable-shared --enable-threads=posix --enable-laguages=all --with-ppl --with-cloog --disable-multilib Thread model: posix gcc version 4.9.1 (GCC)
i believe i've hit the same problem, here's the footgun reproducer i came up with: #include <functional> #include <cstdio> int foo = 42; int const& bar() { return foo; } int main() { std::function<int const& ()> f{ [] () { return bar(); } }; int const& rfoo = f(); printf("%p %p\n", (void*)&foo, (void*)&rfoo); return &foo == &rfoo; } this is g++ (GCC) 5.3.1 20160406 (Red Hat 5.3.1-6) > g++ -std=c++11 -Wall -Wextra -pedantic -Weffc++ -W lambdaref.cc && ./a.out 0x60204c (nil) the problem is that the deduced return type of the lambda is a value type, never a reference type. this caught me by surprise, but it's the same rule as for "auto". if the C++ committee has to make surprising and error-prone type inference rules, then at least implementations like g++ could give a warning about returning a reference from a lambda that is implicitly copied to a value, only to be implicitly converted again into nothing. Visual Studio 2013 gives a "warning C4172 returning address of local variable or temporary" from somewhere inside its std::function code.
(In reply to Michael Stahl from comment #1) > i believe i've hit the same problem I don't think so. The original bug report is for 4.9.3, and seems to be an actual compiler bug that is fixed already in GCC 5 and later. Your case is invalid code. While I agree a warning would be nice, it's not the same as a bug in 4.9.3 that has been fixed.
Oops, the original report was for 4.9.1, but the bug is still present in 4.9.3
Confirming the original report, which is a real bug. N.B. for the different issue in comment 1, G++ will warn but only with -Wsystem-headers, because the problem is inside the <functional> header: /home/jwakely/gcc/6/include/c++/6.0.0/functional:1726:40: warning: returning reference to temporary [-Wreturn-local-addr] std::forward<_ArgTypes>(__args)...); ^
(In reply to Jonathan Wakely from comment #2) > (In reply to Michael Stahl from comment #1) > > i believe i've hit the same problem > > I don't think so. The original bug report is for 4.9.3, and seems to be an > actual compiler bug that is fixed already in GCC 5 and later. > > Your case is invalid code. While I agree a warning would be nice, it's not > the same as a bug in 4.9.3 that has been fixed. I've created PR 70692 for the missing warning on the invalid code, since it's a different problem to the one in this PR.
I can't reproduce the original ICE with either version.
(In reply to Jonathan Wakely from comment #5) > (In reply to Jonathan Wakely from comment #2) > > (In reply to Michael Stahl from comment #1) > > > i believe i've hit the same problem > > > > I don't think so. The original bug report is for 4.9.3, and seems to be an > > actual compiler bug that is fixed already in GCC 5 and later. > > > > Your case is invalid code. While I agree a warning would be nice, it's not > > the same as a bug in 4.9.3 that has been fixed. > > I've created PR 70692 for the missing warning on the invalid code, since > it's a different problem to the one in this PR. ah right, I think this just reminded me of a bug whose number I was trying to remember for a different bug...
Closing as fixed long ago.