2016-09-21 2 views
20

Я не уверен в возможной ошибке GCC при инициализации std::function с помощью функции лямбда-функции, регистрирующей this в инициализаторе нестатических данных. Это разрешено стандартом C++ или это UB?Ошибка сегментации для лямбда-функции в инициализаторе нестатического элемента данных

Учитывая следующий код:

#include <functional> 
#include <iostream> 

template <typename T> 
struct A { 
     T x = 0; 
     std::function<void(T)> f = [this](T v) { x = v; }; 
}; 

int main() { 
     A<int> a; 
     a.f(1); 
     std::cout << a.x << "\n"; 
} 

В моем понимании, он должен напечатать 1. Однако при построении с помощью GCC 5.4.0 или GCC 6.2.0, a.f(1) испускает ошибку сегментации, потому что захваченный указатель this имеет значение NULL.

Следующие варианты работают, как я ожидал:

  • Использование списка конструктор инициализатора:

    template <typename T> 
    struct B { 
        B() : f([this](T v) { x = v; }) {} 
        T x = 0; 
        std::function<void(T)> f; 
    }; 
    
  • Без шаблона:

    struct C { 
        int x = 0; 
        std::function<void(int)> f = [this](int v) { x = v; }; 
    }; 
    

Кроме того, когда построен с лязг 3.8.0, все три версии ведут себя так, как я ожидаю, что не означает, что это не UB.

+7

Я склоняюсь к ошибке GCC: 'this' не должен * никогда * быть нулевым. – Quentin

+0

Мне интересно, что VS2015 делает :) Может кто-нибудь проверить пожалуйста? – Rakete1111

+3

@ Rakete1111 Работы по обновлению MSVS 2015 3. – NathanOliver

ответ

0

Ваш код компилируется и запускается на VS2015 (windows). Так что это, вероятно, ошибка компилятора.

Кроме того, если вы удалите шаблон он работает на http://cpp.sh/ Попробуйте этот код:

#include <functional> 
#include <iostream> 

struct A { 
     int x = 0; 
     std::function<void(int)> f = [this](int v) { x = v; }; 
}; 

int main() { 
     A a; 
     a.f(1); 
     std::cout << a.x << "\n"; 
} 

работает исходный код на cpp.sh дает:

internal compiler error: in tsubst_copy, at cp/pt.c:12569 
Please submit a full bug report 

Так что я думаю, что это ошибка

+0

ли что-то работает или не работает на VS, обычно не указывает на много полезности в отношении законности этой вещи ...: P и cpp.sh использует GCC 4.9.2, но поскольку вы изменили код, я не уверен, что это означает слишком много. –

+2

работает исходный код на cpp.sh дает: 7: 35: внутренняя ошибка компилятора: в tsubst_copy, cp/pt.c: 12569 Просьба представить полный отчет об ошибке, поэтому я думаю, что это ошибка –

+0

Спасибо за это. Надеемся, что OP [перейдет в GCC Bugzilla и сообщит об этом как таковой] (https://gcc.gnu.org/bugzilla/enter_bug.cgi?product=gcc). –

1

Вы не можете сделать:

template <typename T> 
struct A { 
    T x = 0; 
    std::function<void(T)> f = [this](T v) { x = v; }; 
}; 

Как this не существует, когда вы определяете f. Вы должны initilize f в конструкторе, такие как:

A(){ f = [this](T v){ x=v; } } 

Он работал с G ++ 4.8.