How do you reserve space with malloc for a struct?

0

I do not know if I'm doing the memory reserve properly for my struct, this is my code:

 datos_entrada = (pmanager_t *)malloc(sizeof(pmanager_t)*(n_max_cintas));

It gives me problems when trying to write in a pipe according to valgrind and not

I understand why:

fprintf(des_pipe, "%i", datos_entrada[i].id_cinta);

My whole code would be this one. I have commented the exec, because it is not the problem and so I only pass this document.

/*
 *
 * factory_manager.c
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <stddef.h>
#include <semaphore.h>
#include <sys/stat.h>
#include <string.h>
#include "queue.h"

int n_max_cintas;/*Numero maximo de process_manager y por tanto de colas*/
int n_real_cintas = 0;

int l_id_cinta = 0;
int l_tam_cinta = 0;
int l_n_elementos = 0;
int tuberia[2];

char id_cinta_c[4];
char semaforo_c[4];
char tam_cinta_c[4];
char n_elementos_c[4];

char buffer;
char *buffer_w;

sem_t *semaforo;
char* nombre_semaforo = "/semaforo_cinta759";

typedef struct process_manager {

    int id_cinta;/*Id de la cinta*/
    int tam_cinta;/*Numero maximo de elementos que puede tener una cinta*/
    int n_elementos;/*Numero de elementos que se debe generar en la cinta*/
} pmanager_t;

pmanager_t *datos_entrada; /*Definimos un datos: de tipo pmanager_t para almacenar cada uno de los datos necesarios para cada hijo*/


void parser (const char * argv);/**/

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

    semaforo = sem_open(nombre_semaforo, O_CREAT, 0644, 0);

    parser(argv[1]);/*Lo metemos en el parser*/

    pipe(tuberia);

    int pid [n_max_cintas];

    for (int i = 0; i < n_real_cintas; i++) {

        pid[i] = fork();

        if(pid[i] == 0){
            close(0);
            dup(tuberia[0]);
            close(tuberia[0]);
            close (tuberia[1]);

            sprintf(id_cinta_c, "%d", datos_entrada[i].id_cinta);
            sprintf(tam_cinta_c,"%d",datos_entrada[i].tam_cinta);
            sprintf(n_elementos_c,"%d", datos_entrada[i].n_elementos);

            printf("[OK][factory_manager] Process_manager with id %i has been created.\n", datos_entrada[i].id_cinta);

            /*execlp("./process", id_cinta_c, nombre_semaforo, tam_cinta_c, n_elementos_c,NULL);
            perror("[ERROR]Exec no ejecutado.\n");*/

            printf("adios\n");
            exit (-1);
        }
    }

    printf("hola");


    close (tuberia[0]);


    FILE *des_pipe = fdopen( dup(tuberia[1]), "a+" );

    for (int i = 0; i < n_real_cintas; i++){


        fprintf(des_pipe, "%i", datos_entrada[i].id_cinta);
        int a;
        sem_post(semaforo);
        if( (a = wait(&pid[i]) == 0)){

            printf("[OK][factory_manager] Process_manager with id %i has finished.\n", datos_entrada[i].id_cinta);
        }

        else{

            printf("%i\n", a);
            printf("[ERROR][factory_manager] Process_manager with id %i has finished with errors.\n", datos_entrada[i].id_cinta);
        }
    }

    printf("[OK][factory_manager] Finishing.\n");
    return 0;

}



void parser (const char * argv){
    FILE* desc_fichero;
    int leido;


    /*-------------------------------------ABRO EL FICHERO-------------------------------------------*/
    desc_fichero = fopen(argv, "r");

    if (desc_fichero == NULL) {

        perror("[ERROR][factory_manager] Invalid file1.");
        exit(-1);
    }

    /*-------------------------------------LEO EL FICHERO-------------------------------------*/

    if((fscanf(desc_fichero, "%d", &n_max_cintas)) == EOF || n_max_cintas <= 0){/*Le el primer valor y lo guarda en n_max_cintas */

        fprintf(stderr, "[ERROR][factory_manager] Invalid file2.");

        if(fclose(desc_fichero) != 0) {

            perror("[ERROR][factory_manager] Invalid file3.");
            exit(-1);
        }
    }
    datos_entrada = (pmanager_t *)malloc(sizeof(pmanager_t)*(n_max_cintas));

    while(leido != EOF){

        leido=fscanf(desc_fichero, "%i %i %i", &l_id_cinta, &l_tam_cinta, &l_n_elementos);

        if(leido != 3 && leido != EOF){

            fprintf(stderr, "[ERROR][factory_manager] Invalid file.4\n"); /*Mostramos el mensaje por la salida de error estándar*/
            fclose(desc_fichero);
            exit (-1);
        }

        if(l_id_cinta <= 0 || l_tam_cinta <= 0 || l_n_elementos <= 0){

            perror("[ERROR][factory_manager] Invalid file5.\n");
            exit(-1);
        }

        else{

            if(leido != EOF){

                pmanager_t cinta;

                cinta.id_cinta = l_id_cinta;
                cinta.tam_cinta = l_tam_cinta;
                cinta.n_elementos = l_n_elementos;

                datos_entrada[n_real_cintas] = cinta;

                n_real_cintas++;
            }
        }
    }


    /*-------------------------------------CIERRO EL FICHERO-------------------------------------*/
    if(fclose(desc_fichero) != 0) {

        perror("[ERROR][factory_manager] Invalid file6.");
        exit(-1);
    }


    if(n_real_cintas > n_max_cintas){

        perror("[ERROR][factory_manager] Invalid file7.");
        exit(-1);
    }
}

What the valgrind returns to me is this:

> goh@goh:~/Escritorio/practica$ valgrind --leak-check=full ./factory
> p.txt
> ==9563== Memcheck, a memory error detector
> ==9563== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
> ==9563== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info
> ==9563== Command: ./factory p.txt
> ==9563== 
> ==9563== Conditional jump or move depends on uninitialised value(s)
> ==9563==    at 0x109177: parser (factory_manager.c:140)
> ==9563==    by 0x108C59: main (factory_manager.c:53)
> ==9563==  [OK][factory_manager] Process_manager with id 1 has been created.
> ==9563== Invalid read of size 4
> ==9563==    at 0x50A48F4: vfprintf (vfprintf.c:1275)
> ==9563==    by 0x50AD546: fprintf (fprintf.c:32)
> ==9563==    by 0x108EAD: main (factory_manager.c:92)
> ==9563==  Address 0xc0 is not stack'd, malloc'd or (recently) free'd
> ==9563== 
> ==9563== 
> ==9563== Process terminating with default action of signal 11 (SIGSEGV)
> ==9563==  Access not within mapped region at address 0xC0
> ==9563==    at 0x50A48F4: vfprintf (vfprintf.c:1275)
> ==9563==    by 0x50AD546: fprintf (fprintf.c:32)
> ==9563==    by 0x108EAD: main (factory_manager.c:92)
> ==9563==  If you believe this happened as a result of a stack
> ==9563==  overflow in your program's main thread (unlikely but
> ==9563==  possible), you can try to increase the size of the
> ==9563==  main thread stack using the --main-stacksize= flag.
> ==9563==  The main thread stack size used in this run was 8388608.
    
asked by Alfonso Rodríguez 27.04.2017 в 10:59
source

1 answer

0
if((fscanf(desc_fichero, "%d", &n_max_cintas)) == EOF || n_max_cintas <= 0){

    fprintf(stderr, "[ERROR][factory_manager] Invalid file2.");

    if(fclose(desc_fichero) != 0) {

        perror("[ERROR][factory_manager] Invalid file3.");
        exit(-1);
    }
}
datos_entrada = (pmanager_t *)malloc(sizeof(pmanager_t)*(n_max_cintas));

In that fragment you read an integer of a file and then you use that value to make a memory reservation ... What happens if the scan gives EOF and when closing the file you get a 0 ? That exit is not executed and you make a memory reservation based on a value of n_max_cintas dirty (remember that the reading has failed).

You should try something like this:

if((fscanf(desc_fichero, "%d", &n_max_cintas)) == EOF || n_max_cintas <= 0){

    fprintf(stderr, "[ERROR][factory_manager] Invalid file2.");

    if(fclose(desc_fichero) != 0) {

        perror("[ERROR][factory_manager] Invalid file3.");
        exit(-1);
    }
    else
    {
      // Aqui deberias hacer algo
    }
}
else
{
  datos_entrada = (pmanager_t *)malloc(sizeof(pmanager_t)*(n_max_cintas));
  // ...
}
    
answered by 27.04.2017 в 13:50