jeudi 26 octobre 2017

Segmentation fault when calling lambda returns from high-order function in C++11

I have the following code which trying to define procedures in CPS form.

#include <iostream>
#include <utility>
#include <type_traits>
#include <string>

using namespace std;


template <typename T> using Func = std::function<T>;
template <typename T> using Cont = Func<void (T &&)>;
template <typename T, typename U> using Proc = Func<void (T &&, Cont<U>)>;

template <typename T> struct RevProc;
template <typename T, typename U> struct RevProc<Proc<T, U>> {
  using ArgType = T;
  using RetType = U;
};

template <typename P1, typename P2> auto pipe(P1 proc1, P2 proc2)
  -> Proc<typename RevProc<P1>::ArgType, typename RevProc<P2>::RetType> {
  using T = typename RevProc<P1>::ArgType;
  using U = typename RevProc<P2>::ArgType;
  static_assert(is_same<U, typename RevProc<P1>::RetType>::value,
    "Mismatch procedure type.");
  using V = typename RevProc<P2>::RetType;
  return [&] (T &&t, Cont<V> pass) {
    proc1(move(t), [&] (U &&u) {
      proc2(move(u), pass);
    });
  };
}
template <typename P1, typename P2, typename... Ps> auto pipe(P1 proc1, P2 proc2, Ps ...procs)
  -> Proc<typename RevProc<P1>::ArgType, typename RevProc<decltype(pipe(proc2, procs...))>::RetType> {
  auto proc2s = pipe(proc2, procs...);
  return pipe(proc1, proc2);
}

int main() {
  Func<void ()> var1;
  Cont<int> var2([] (int &&x) {});
  Proc<int, int> var3([] (int &&x, Cont<int> pass) {
    pass(x + 1);
  });
  auto var4 = pipe(var3, var3);
  var4(42, [] (int &&x) {
    cout << x << endl;
  });
  Proc<string, int> var5([] (string &&str, Cont<int> pass) {
    pass(str.length());
  });
  // auto var6 = pipe(var5, var5);
  Proc<int, int> var7 = pipe(var3, var3, var3);
  // var7(42, [] (int &&x) {
  //   cout << x << endl;
  // });
  auto var8 = pipe(var5, var3, var3);
  var8("something", [] (int &&x) {
    cout << x << endl;
  });

  return 0;
}

If I uncomment var6 line, the compiler throw an error as expect. However, if either var7 or var8's calling is uncommented, then the code passes compilation but a random segmentation fault or bus error would be triggered at runtime. The code is safe during building the lambda but crashing when applying them.

Thanks for pointing out my faulty.


It may be useful to complement that it runs well if I modify the code to

var7 = pipe(var3, pipe(var3, var3));

So as var8.

Aucun commentaire:

Enregistrer un commentaire