Std :: bad_function_call when calling std :: swap in visual studio

I am trying to transfer my code from linux to windows. However, with Visual Studio, my code crashes with the following error:

Microsoft C ++ exception: std :: bad_function_call in memory cell

This is my code:

#include <functional>

class Foo {
public:
    Foo(int) : m_deleter{ []() {} } {}
    Foo(const Foo &) = delete;
    Foo(Foo &&) = default;
    Foo & operator=(const Foo &) = delete;
    Foo & operator=(Foo &&) = default;
    ~Foo()
    {
        m_deleter();
    }
private:
    std::function<void()> m_deleter;
};

int main() {
    Foo foo(1);
    Foo bar(2);
    std::swap(foo, bar);
}

Failure to use std::swap. On Linux, it worked flawlessly.

Oddly enough, when I try to compile it online via GCC, it doesn't work either. What am I doing wrong and why does it work on working with Clang (3.5).

EDIT: Turns out it crashes with Visual Studio 2015 and GCC 4.9.2, but not with Clang 3.5.

+4
source share
3 answers

Introduction

; m_deleter Foo , .

std::swap , m_deleter.


std:: bad_function_call?
std:: bad_function_call , std::function, .



, , :

 1 #include <functional>
 2 #include <utility>

 3 struct A {
 4   A () 
 5     : _cb {[]{}}
 6   { } 
 7   
 8   A (A&& src)
 9     : _cb (std::move (src._cb))
10   { } 
11   
12   A& operator= (A&& src)
13   {
14     _cb = std::move (src._cb);
15     return *this;
16   } 
17   
18 
19   ~A () {
20     _cb ();
21   } 
22   
23   std::function<void()> _cb;
24 };

25 void swap (A& lhs, A& rhs) {
26   A temporary = std::move (lhs);
27           lhs = std::move (rhs);
28           rhs = std::move (temporary);
29 } 

30 int main() {
31   A x, y;
32   swap (x, y);
33 } 

swap , , , , _cb - , temporary._cb 14; .


~A::A () {
  if (_cb) // check if callable
    _cb (); 
}
+3

std::swap() . swap() , m_deleter . , m_deleter(); std::bad_function_call, m_deleter .

std::swap (gcc4.9.1, ubuntu) :

template<typename _Tp>
  inline void
  swap(_Tp& __a, _Tp& __b)
  noexcept(__and_<is_nothrow_move_constructible<_Tp>,
           is_nothrow_move_assignable<_Tp>>::value)
  {
    _Tp __tmp = std::move(__a);
    __a = std::move(__b);
    __b = std::move(__tmp);
  }

swap __tmp ( Foo) std::function<void()> m_deleter . , m_deleter();

+2

Visual ++ 2013, ; :

#include <functional>

class Foo {
public:
    Foo(int) : m_deleter{ []() {} } {}
    Foo(const Foo &) = delete;
    Foo(Foo &&src) : m_deleter(std::move(src.m_deleter)) { };
    Foo & operator=(const Foo &) = delete;
    Foo & operator=(Foo &&src) { m_deleter = std::move(src.m_deleter); return *this; }
    ~Foo()
    {
        m_deleter();
    }
private:
    std::function<void()> m_deleter;
};

int main() {
    Foo foo(1);
    Foo bar(2);
    std::swap(foo, bar);
}

Visual Studio, , . std::swap. VC :

_Ty _Tmp = _Move(_Left);
_Left = _Move(_Right);
_Right = _Move(_Tmp);

. , _Tmp. , m_deleter , " " :

Visual Studio debugger showing <code> std :: swap </code> call with temporary variable whose destructor will cause a crash

, , , std::function, . .

...

, Visual Studio 2015 GCC 4.9.2, Clang 3.5.

, Clang 3.5:

terminate called after throwing an instance of 'std::bad_function_call'

  what():  bad_function_call

bash: line 7: 25250 Aborted                 (core dumped) ./a.out

http://coliru.stacked-crooked.com/, clang++ --version clang version 3.5.0 (tags/RELEASE_350/final 217394).

0

All Articles