mardi 18 juin 2019

Segfault when not specifying return type of lambda function

I have this example code:

#include <functional>
#include <iostream>
#include <string>

void f(std::function<const std::string&()> fn) {
  std::cout << "in f" << std::endl;
  std::cout << "str: " << fn() << std::endl;
}

int main() {
  std::string str = "a";

  auto fn1 = [&]() { return str; };
  auto fn2 = [&]() { const std::string& str2 = str; return str2; };
  auto fn3 = [&]() -> const std::string& { return str; };

  std::cout << "in main" << std::endl;
  std::cout << "fn1: " << fn1() << std::endl;
  std::cout << "fn2: " << fn2() << std::endl;
  std::cout << "fn3: " << fn3() << std::endl;

  f(fn1);  // Segfaults
  f(fn2);  // Also segfaults
  f(fn3);  // Actually works

  return 0;
}

When I first wrote this I expected that calling fn1() inside f() would properly return a reference to the str in main. Given that str is allocated until after f() returns, this looked fine to me. But what actually happens is that trying to access the return of fn1() inside f() segfaults.

The same thing happens with fn2(), but what is surprising is that fn3() works properly.

Given that fn3() works and fn1() doesn't, is there something I'm missing about how C++ deduces the return values of lambda functions? How would that create this segfault?

For the record, here are the outputs if I run this code:

calling only f(fn1):

in main
fn1: a
fn2: a
fn3: a
in f
str: a

calling only f(fn2):

in main
fn1: a
fn2: a
fn3: a
in f
Segmentation fault (core dumped)

calling only f(fn3):

in main
fn1: a
fn2: a
fn3: a
in f
Segmentation fault (core dumped)

Aucun commentaire:

Enregistrer un commentaire