Структура с переменной длиной элемента приводит к «Ошибка сегментации 11» - PullRequest
0 голосов
/ 30 августа 2018

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

У меня есть две части кода (код A и код B), который делает одно и то же, а именно: инициализирует блок памяти случайными значениями. Обе части кода компилируются просто отлично, однако, когда я выполняю код B, я получаю ошибку ошибки сегментации 11, и код перестает выполняться. Код B работает со структурой переменной длины, и я считаю, что это создает проблему. Однако я не знаю, как это исправить.

Мой вопрос: Кто-нибудь знает, в чем причина проблемы и как ее исправить? Мне бы очень хотелось, чтобы код B работал, так как это удобно в коде позже. Я вставил обе части кода ниже. Система, в которой я тестировал этот код, - macOS.

Любая помощь будет принята с благодарностью!

Код A:

#include <stdio.h>
#include <math.h>
#include <stdlib.h>

#define DEBUG

/*
  Function prototypes
*/
void init_rand(float *p, int size);


int main(int argc, char const *argv[])
{

  int neurons [] = {10,10,10}; // use this array to define the neuralnet
  int layers = sizeof(neurons)/sizeof(int); // this calculates the amount of layers in the neuralnet (i.e. the amount of members in the array 'neurons')

  // array of pointers for the memory given by malloc
  float *pwl[layers];
  float *pbl[layers];
  float *pzl[layers];
  float *pal[layers];

  for (int i = 1; i < layers; i++) // create memory for the matrices and assign the start adress of each matrix to the pointers
  {
    pwl[i] = (float *)malloc(neurons[i]*neurons[(i-1)]*sizeof(float));
    pbl[i] = (float *)malloc(neurons[i]*sizeof(float));
    pzl[i] = (float *)malloc(neurons[i]*sizeof(float));
    pal[i] = (float *)malloc(neurons[i]*sizeof(float));
  }

  for (int i = 1; i < layers; i++) // initialize the weights and the biases with random values
  {
    init_rand(pwl[i], neurons[i]*neurons[i-1]);
    init_rand(pbl[i], neurons[i]);
  }

  return 0;
}

/*
  Random generator with a gaussian distribution. Mean = 0, Variance = 1
*/
double gaussrand()
{
    static double V1, V2, S;
    static int phase = 0;
    double X;

  if(phase == 0)
  {
        do
    {
            double U1 = (double)rand() / RAND_MAX;
            double U2 = (double)rand() / RAND_MAX;

            V1 = 2 * U1 - 1;
            V2 = 2 * U2 - 1;
            S = V1 * V1 + V2 * V2;
            } while(S >= 1 || S == 0);

        X = V1 * sqrt(-2 * log(S) / S);
    } else
        X = V2 * sqrt(-2 * log(S) / S);

    phase = 1 - phase;

    return X;
}

/*
  This function initializes a float array with random gaussian distributed numbers
*/
void init_rand(float *p, int size)
{
  for (int i = 0; i < size; i++, p++)
  {
    *p = (float)gaussrand();

#ifdef DEBUG
    printf("%d:*p = %f\n", i, *p); //
#endif
  }
}

Код B:

#include <stdio.h>
#include <math.h>
#include <stdlib.h>

#define DEBUG

struct neuralnet
{
  int struct_size;
  float *pwl[0];
  float *pbl[0];
  float *pzl[0];
  float *pal[0];
};

/*
  Function prototypes
*/
void init_rand(float *p, int size);
struct neuralnet* create_neuralnet(struct neuralnet* pnet, int layers);


int main(int argc, char const *argv[])
{

  int neurons [] = {10,10,10}; // use this array to define the neuralnet
  int layers = sizeof(neurons)/sizeof(int); // this calculates the amount of layers in the neuralnet

  struct neuralnet *pnet; // create a struct neuralnet pointer

  pnet = create_neuralnet(pnet, layers); // this function will create a neuralnet structure with variable size members

  for (int i = 1; i < layers; i++) // create memory for the matrices and assign the start adress of each matrix to the pointers
  {
    pnet->pwl[i] = (float *)malloc(neurons[i]*neurons[(i-1)]*sizeof(float));
    pnet->pbl[i] = (float *)malloc(neurons[i]*sizeof(float));
    pnet->pzl[i] = (float *)malloc(neurons[i]*sizeof(float));
    pnet->pal[i] = (float *)malloc(neurons[i]*sizeof(float));
  }

  for (int i = 1; i < layers; i++) // initialize the weights and the biases with random values
  {
    init_rand(pnet->pwl[i], neurons[i]*neurons[i-1]);
    init_rand(pnet->pbl[i], neurons[i]);
  }

  return 0;
}

/*
  Random generator with a gaussian distribution. Mean = 0, Variance = 1
*/
double gaussrand()
{
    static double V1, V2, S;
    static int phase = 0;
    double X;

    if(phase == 0)
  {
        do
    {
            double U1 = (double)rand() / RAND_MAX;
            double U2 = (double)rand() / RAND_MAX;

            V1 = 2 * U1 - 1;
            V2 = 2 * U2 - 1;
            S = V1 * V1 + V2 * V2;
            } while(S >= 1 || S == 0);

        X = V1 * sqrt(-2 * log(S) / S);
    } else
        X = V2 * sqrt(-2 * log(S) / S);

    phase = 1 - phase;

    return X;
}

/*
  This function initializes a float array with random gaussian distributed numbers
*/
void init_rand(float *p, int size)
{
  for (int i = 0; i < size; i++, p++)
  {
    *p = (float)gaussrand();

#ifdef DEBUG
    printf("%d:*p = %f\n", i, *p); //
#endif
  }
}

/*
    This function creates the structure with members of variable length
*/
struct neuralnet* create_neuralnet(struct neuralnet *pnet, int layers)
{
  pnet = (struct neuralnet *)malloc(sizeof(*pnet) + sizeof(float *) * layers * 4);
  return pnet;
}
...