简体   繁体   中英

C dynamic array of structures, no errors, program terminates when ran

When ran, the program immediately terminates from an issue I believe to be associated with memory allocation. The main function only calls this function and another to delete the memory allocated

DrinkMachine *create(void){
    FILE *inFile;
    //Pointer to data structure
    DrinkMachine *drinkMachine;
    // Memory allocation
    drinkMachine = calloc(1, sizeof(DrinkMachine));
    if(drinkMachine == NULL)    // Check success
        return NULL;

    // Open the input file for reading
    inFile = fopen("drink_machine.txt" , "r");
    if(!inFile){
        puts("Error opening file");
        return NULL;
    }
    // Read drink count from file
    fscanf(inFile, "%d", &(drinkMachine->numItems));
    printf("DEBUG read file arrayLen: %d\n", drinkMachine->numItems);

    // Dynamically create array of drink item structures 

    drinkMachine->drinkItem = malloc(drinkMachine->numItems*sizeof(DrinkItem));
    if(drinkMachine->drinkItem == NULL){
        puts("ERROR: Failed to allocate memory");
        return NULL;
    }

    // Put information from file into drinkItem structs
    for(int i=0; i < drinkMachine->numItems; ++i){
        fscanf(inFile, "%s %lf %d", (drinkMachine->drinkItem[i].name), &(drinkMachine->drinkItem[i].price), &(drinkMachine->drinkItem[i].drinkLeft));
        printf("DEBUG drink %d is: %s   %lf   %d\n", i, (drinkMachine->drinkItem[i].name), (drinkMachine->drinkItem[i].price), (drinkMachine->drinkItem[i].drinkLeft));
    }

    // Close inFile
    fclose(inFile);

    // Force output to screen
    puts("DEBUG readFile Success!");
    fflush(stdout);

    return drinkMachine;
}

The program ran into errors or wouldn't properly allocate memory and would successfully output the error message when ran, until I put in the line:

drinkMachine->drinkItem = malloc(drinkMachine->numItems*sizeof(DrinkItem));

At this point the program compiles without warning or errors, but terminates immediately when ran without any output. In case it helps, here are the structures:

typedef struct _DrinkItem{
    int id;
    char *name;
    double price;
    int drinkLeft;
    int drinkSold;
} DrinkItem;

typedef struct _DrinkMachine{
    int version;
    int numItems;
    int  drinkLocation;
    DrinkItem *drinkItem;
} DrinkMachine;

You have to allocate storage for each name too. You are reading characters into an unallocated pointer on line 30. You should read the name into a temporary array, get the name's length, allocate (length+1) bytes of storage to name, and strncpy the data over.

You didn't allocate name space, you didn't handle any input error, you use int without verify that it not negative for a size, you didn't use stderr for error, you used reserved identifier and more.

Here a proposition of code, that I think fix all your errors (didn't test it as you didn't give example of input and output):

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

typedef struct DrinkItem {
  int id;
  char *name;
  double price;
  int drinkLeft;
  int drinkSold;
} DrinkItem;

typedef struct DrinkItem {
  int version;
  size_t numItems;
  int drinkLocation;
  DrinkItem *drinkItems;
} DrinkMachine;

static void helper_free(DrinkItem *drinkItems, size_t n) {
  for (size_t i = 0; i < n; i++) {
    free(drinkItems[i].name);
  }
  free(drinkItems);
}

DrinkMachine *create(char const *path) {
  FILE *inFile = fopen(path, "r");
  if (!inFile) {
    fprintf(stderr, "Error opening file");
    return NULL;
  }

  size_t numItems;
  if (fscanf(inFile, "%zu", &numItems) != 1) {
    fprintf(stderr, "Error parsing\n");
    return NULL;
  }
#ifndef NDEBUG
  printf("DEBUG read file arrayLen: %zu\n", numItems);
#endif

  DrinkItem *drinkItems = malloc(numItems * sizeof *drinkItems);
  if (!drinkItems) {
    fprintf(stderr, "ERROR: Failed to allocate memory");
    return NULL;
  }
  for (size_t i = 0; i < numItems; ++i) {
    char *name = malloc(100);
    if (!name) {
      helper_free(drinkItems, i);
      fprintf(stderr, "ERROR: Failed to allocate memory");
      return NULL;
    }
    double price;
    int drinkLeft;
    if (fscanf(inFile, "%99s %lf %d", name, &price, &drinkLeft) != 3) {
      free(name);
      helper_free(drinkItems, i);
      fprintf(stderr, "Error parsing\n");
      return NULL;
    }
    drinkItems[i] =
        (DrinkItem){.name = name, .price = price, .drinkLeft = drinkLeft};

#ifndef NDEBUG
    printf("DEBUG drink %zu is: %s   %lf   %d\n", i, name, price, drinkLeft);
#endif
  }

  fclose(inFile);

  DrinkMachine *drinkMachine = malloc(sizeof *drinkMachine);
  if (!drinkMachine) {
    helper_free(drinkItems, numItems);
    fprintf(stderr, "ERROR: Failed to allocate memory");
    return NULL;
  }
  *drinkMachine =
      (DrinkMachine){.drinkItems = drinkItems, .numItems = numItems};

#ifndef NDEBUG
  puts("DEBUG readFile Success!\n");
#endif

  return drinkMachine;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM