I am implementing a doubly linked list and I am getting a segfault when I try to access a member veritable of an object pointed at by a member pointer. My linked list is composed of Nodes, which have a value and a next and previous pointer
String (This is the bare bones implementation from a previous project):
class String{
    public:
    int len;
    char *str;
    String()
    :len(0), str(nullptr){}
    String(char const* S)
    :len(strlen(S)), str(new char[len +1]){
        assert(S != 0);
        strcpy(str, S);
    }
    ~String(){
        delete[]str;
    }
};
Node (I know this doesn't implement 'the big three', I would rather keep this class to a minimum):
#include <initializer_list>
    template<typename T>
    struct Node{
      T value;
      Node* next;
      Node* prev;
      Node() = default;
      Node(T t, Node* n, Node* p)
      :value(t), next(n), prev(p){}
      Node & operator=(const Node & N){
        value = N.value;
        next = N.next;
        prev = N.prev;
        return *this;
      }
    };
Doubly linked list:
template<typename T>
struct List
{
  List(std::initializer_list<T>);
  Node<T>* head;
  Node<T>* tail;
  List()
  :head(nullptr), tail(nullptr){}
  //copy constructor
  List(const List<T> & l){
    Node<T>* p = l.head;
    head = p;
    Node<T>* past;
    while(p){
      Node<T>* q = new Node<T>;
      *q = *p;
      if(head == p){
        head = q;
      }else{
        past->next = q;
        q->prev = past;
      }
      past = q;
      p = q->next;
    }
    tail = past;
  }
  //copy assignment
  List & operator=(const List & L){
    List temp = L;
    swap (*this, temp);
    return *this;
  }
  Node<T>* getHead()const{
    return head;
  }
  Node<T>* getTail()const{
    return tail;
  }
  void swap(List a, List b){
    Node<T>* temp1 = a.getHead();
    Node<T>* temp2 = a.getTail();
    a.head = b.getHead();
    a.tail = b.tail;
    b.head = temp1;
    b.tail = temp2;
  }
  void push_back(T t){
    Node<T>* p = new Node<T>(t, nullptr, tail);
    if(tail){
      tail->next = p; //Segfault occurs here
    }else{
      head = p;
    }
    tail = p;
  }
  int compare(const List<T> & b)const{
    Node<T>* temp1 = this->head;
    Node<T>* temp2 = b.head;
    while (temp1 != this->tail && temp2 != b.tail) {
      if (temp1->value < temp2->value)
        return -1;
      if (temp2->value < temp1->value)
        return 1;
    }
    if (temp1 == this->tail) {
      if (temp2 != this->tail)
        return -1; // [first1, last1) is a prefix of [first2, last2)
      else
        return 0;  // [first1, last1) and [first2, last2) are equivalent
    }
    else {
      return 1;    // [first2, last1) is a prefix  of [first1, last1)
    }
  }
  size_t size()const{
    size_t n = 0;
    Node<T> *p = head;
    while (p){
      ++n;
      p = p->next;
    }
    return n;
  }
  void clear(){
    Node<T> *p = head;
    while(p){
      Node<T>* q = p-> next;
      delete[] p;
      p = q;
    }
    head = tail = nullptr;
  }
  ~List<T>(){
    clear();
  }
};
template<typename T>
List<T>::List(std::initializer_list<T> list)
{
  for (T const& elem : list)
    push_back(elem);
}
Main:
int main()
{
    List<String> v1 =  {"a", "b", "c"}; //segfault occurs on second pass of initialization loop
    return 0;
}
Any help is appreciated!
 
     
    