C ++ вектор, не хранящий класс - PullRequest
0 голосов
/ 30 июня 2018

Я пишу простую нейронную сеть с прямой связью на c ++, однако, когда я пытаюсь сохранить свой класс нейронов в моей структуре слоев, он вылетает и выдает следующее:

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

what(): std::bad_array_new_length

This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information.

Вот моя программа:

#include <iostream>
#include <random>
#include <vector>
using namespace std;
random_device e;

int randomG(int min, int max){
  return (e()%(max-min))+min;
}

int f(int v){
  return v+5;
}

class neuron{
public:
  neuron(int _insN, int _funtype){
    insN=_insN;funtype=_funtype;
  }
  float out;
  void genWeights(){
    for (int i = 0; i < insN; i++){
      weights[i]=float(randomG(1,1000))/100;
    }
  }
  float parceOut(float* ins){
    float preOut=0;
    for (int i = 0; i < insN; ++i){
      preOut+=(weights[i]*ins[i]);
    }
    out=activation(preOut, funtype);
  }
private:
  float ReLU(float f){
    if (f<=0){return f*0.01;}
    else {return f;}
  }
  float Softmax(float f){
    return f;
  }
  float activation(float f, int function){
    switch(function){
    case(1): return ReLU(f); break;
    case(2): return f; break;
    case(3): return Softmax(f); break;
    }
  }
  int insN;
  int funtype;
  float* weights = new float[insN];
};

struct layer{
  int insN=1, neuronN=1;
  float* outs=new float[neuronN];
  vector<neuron> nS;
  void generateNeurons(){
    for(int i=0;i<1;i++){
      nS.push_back(neuron(insN,1));
    }
  }
};

int main(int argc, char *argv[])
{
  layer input;
  input.insN=1;
  input.neuronN=5;
  input.generateNeurons();
  cin.get();
  return 0;
}

Я не думаю, что это трудно понять, но если это так, я пытаюсь создать вектор с моим классом нейронов в структуре моего слоя, но даже когда я помещаю только один нейрон в вектор, он говорит, что недостаточно памяти, выделенной для программы. Я пытался преобразовать класс нейронов в структуру, но это не помогло.

Ответы [ 2 ]

0 голосов
/ 30 июня 2018

Элемент weights инициализируется до инициализации insN. Доступ к значению insN для выполнения этого дает неопределенное поведение, и неопределенный объем памяти выделяется оператором new. Это является причиной исключения, которое сообщает bad_array_new_length (на практике выделенное число, вероятно, превышает доступную память на вашем компьютере, хотя это просто случайность с вашим компилятором).

Это происходит до инициализации insN в конструкторе.

Одним частичным исправлением для этого будет удаление инициализатора из тела класса И изменение конструктора на

neuron(int _insN, int _funtype) : insN(_insN), funtype(_funtype), weights(new float[_insN])
{}

Даже если это исправлено, у вашего кода также есть множество других проблем. Я приведу здесь неполный список.

std::vector предполагает, что его элементы имеют конструктор рабочей копии и оператор присваивания. Ваш класс нет, поэтому не играет по правилам. Это означает, что копирование элементов (как, например, может происходить всякий раз при изменении размера вектора) приведет к созданию объектов, которые будут вести себя некорректно (например, изменение элемента weights в одном объекте приведет к непреднамеренному изменению элемента в другом объекте). Посмотрите (например, с помощью Google) «правило трех» или «правило пяти», чтобы решить эту проблему. А еще лучше, сделайте weights a std::vector<float> вместо указателя и следуйте «правилу нуля».

Ваш класс не определяет деструктор, поэтому память, выделенная для weights с использованием оператора new - для каждого объекта - никогда не освобождается. Следовательно, у вас есть утечка памяти - всякий раз, когда создается экземпляр вашего neuron. Снова ищите «правило трех», «правило пяти» или «правило нуля», чтобы найти подход к решению этой проблемы.

Некоторые из вышеприведенных комментариев применимы и к вашему layer классу.

0 голосов
/ 30 июня 2018

Ваш weights член встроенно инициализируется с помощью insN до инициализации insN. Простейшим решением на данный момент было бы изменить объявление члена на:

float* weights;

и конструктор для:

neuron(int _insN, int _funtype) : insN(_insN), funtype(_funtype), weights(new float[insN]) {

}

Обратите внимание, что элементы в списке инициализации инициализируются в порядке их объявления (см. «Порядок инициализации»).

Лучшим долгосрочным решением было бы сделать weights be std::vector<float>, а также любой другой динамический массив float* в вашем коде, который в настоящее время имеет ряд утечек памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...