Thread: Valgrind error Olympic Medals

  1. #1
    Registered User
    Join Date
    Apr 2020
    Posts
    5

    Valgrind error Olympic Medals

    Code:
    #include"projekti.h"
    #include<string.h>
    #include<stdlib.h>
    #include<stdio.h>
    
    struct country *add_country(struct country *array, char *name)
    {
    
      int i;
      for (i = 0; array.name != NULL; i++); //Moving through the array until the first NULL character.
      struct country *newcountry = realloc(array, sizeof(struct country) * (i + 2));  //Allocate space for a country 
      if (newcountry == NULL) {     //+ space for final NULL character
        return NULL;                //allocating failed
      }
    
      char *country_name = malloc(strlen(name) + 1);
      strcpy(country_name, name);   //Copying the name of the country to another string, otherwise the names will overwrite eachother.
    
      newcountry.name = country_name;
      newcountry.medals.gold = 0;
      newcountry.medals.silver = 0;
      newcountry.medals.bronze = 0;
    
      newcountry[i + 1].name = NULL;  //Adding last null char to the array, so that the process can be repeated
    
      return newcountry;
    }
    
    void update_medals(struct country *p, char *name, int number, int g, int s,
                       int b)
    {
    
      int ret;
      int count = 0;                // Int to control if there exists a entered country with the same name.
      for (int i = 0; i < number; i++) {  //Moving through the array of structs, until we find the country with the same name as the input. 
        ret = strcmp(p.name, name); //strcmp returns 0 if the names are equal
        if (ret == 0) {
          p.medals.gold += g;
          p.medals.silver += s;
          p.medals.bronze += b;
          count++;                  //Country found! 
        }
      }
      if (count == 0) {
        printf
            ("Nonexisting country, check spelling or register the entered country before adding medals.\n");
      }
    }
    
    void printtable(struct country *array)
    {
      printf("\n");
      for (int i = 0; array.name != NULL; i++) {  //Moving through the array of structs until NULL character.
        printf("%s %d %d %d\n", array.name, array.medals.gold, array.medals.silver,
               array.medals.bronze);
      }
      printf
          ("\nContinue adding countries and medals, or quit the program with the command 'Q'\n");
    }
    
    void save_table(struct country *p, char *filename, int number)
    {
    
      FILE *file;
      file = fopen(filename, "w");
    
      for (int i = 0; i < number; i++) {
        fwrite(p.name, sizeof(int), 1, file);
      }
    
      fclose(file);
    
      printf("File saved successfully!\n");
    
    }
    
    void load_table(struct country *p, char *filename)
    {
    
      FILE *file;
      file = fopen(filename, "r");
    
      if (file != NULL) {
        while (1) {
          if (feof(file)) {
            printf("File Loaded Successfully!\n");
            break;
          } else {
            fscanf(file, "%s %d %d %d", p->name, &(p->medals.gold),
                   &(p->medals.silver), &(p->medals.bronze));
          }
        }
    
      } else {
        printf
            ("File failed to open due to either wrong name input, or nonexisting file.\n");
        return;
      }
    
      fclose(file);
    }
    
    int main()
    {
    
      struct country *array = malloc(sizeof(struct country));
      array[0].name = NULL;         //Initialize array
    
      char input[80];               //User input line
      char name[20];                //String for handling the country/file name inpu
      int number = 0;               //Keeping track of the number of countries
    
      printf("OLYMPIC MEDALS\n");
      printf
          ("Register a new country with the command prefix 'A'. Example: 'A USA'.\n");
      printf
          ("Add medals to existing countries with the prefix command 'M'. Example: 'M USA 1 1 1'.\n");
      printf("Print the current table with the command 'L'\n");
      printf
          ("Save the existing table to a file with the command prefix 'W'. Example 'W filename'\n");
      printf
          ("Load an existing file with the command prefix 'O'. Example 'O filename'.\n");
      printf("Quit the program with the command 'Q'.\n");
      printf("\n");
    
      while (1) {                   //Loops forever until "break" command
    
        fgets(input, sizeof(input), stdin); //Gets input from user
    
        if (input[0] == 'A') {
          sscanf(input, "%*c %s", name);  //Reads input, ignoring the first "command" character
          array = add_country(array, name);
          if (array == NULL) {
            printf("\nCreating country failed.");
          } else {
            number++;               //Increases the number of countries
          }
          printf
              ("Register another country, or start adding medals to exicting countries.\n");
    
        } else if (input[0] == 'M') {
          if (number == 0) {
            printf
                ("You have yet to register a country! Start by registering at least 1 country!\n");
          } else {
            int g, s, b;            // Gold, Silver and Bronze medal count;
            sscanf(input, "%*c %s %d %d %d", name, &g, &s, &b); //Reads input, ignoring the first "command" character
            update_medals(array, name, number, g, s, b);
          }
    
        } else if (input[0] == 'L') {
          if (number == 0) {
            printf
                ("You have yet to register a country! Start by registering at least 1 country!\n");
          } else {
            printtable(array);
          }
    
        } else if (input[0] == 'W') {
          if (number == 0) {
            printf
                ("You have yet to register a country! Start by registering at least 1 country!\n");
          } else {
            sscanf(input, "%*c %s", name);  //Reads input, ignoring the first "command" character
            save_table(array, name, number);
          }
    
        } else if (input[0] == 'O') {
          if (number == 0) {
            printf
                ("You have yet to register a country! Start by registering at least 1 country!\n");
          } else {
            sscanf(input, "%*c %s", name);  //Reads input, ignoring the first "command" character
            load_table(array, name);
          }
    
        } else if (input[0] == 'Q') {
          free(array);
          printf("Exiting program.\n");
          break;
        }
      }
      return 0;
    }
    I'm getting the following error:

    Code:
    ==15== Memcheck, a memory error detector
    ==15== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
    ==15== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
    ==15== Command: /home/agent/projekti.exe
    ==15== 
    ==15== 
    ==15== HEAP SUMMARY:
    ==15==     in use at exit: 12 bytes in 2 blocks
    ==15==   total heap usage: 9 allocs, 7 frees, 12,996 bytes allocated
    ==15== 
    ==15== 12 bytes in 2 blocks are definitely lost in loss record 1 of 1
    ==15==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==15==    by 0x108BF0: add_country (projekti.c:16)
    ==15==    by 0x10914D: main (projekti.c:117)
    ==15== 
    ==15== LEAK SUMMARY:
    ==15==    definitely lost: 12 bytes in 2 blocks
    ==15==    indirectly lost: 0 bytes in 0 blocks
    ==15==      possibly lost: 0 bytes in 0 blocks
    ==15==    still reachable: 0 bytes in 0 blocks
    ==15==         suppressed: 0 bytes in 0 blocks
    ==15== 
    ==15== For counts of detected and suppressed errors, rerun with: -v
    ==15== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
    Any ideas where the problem lies?
    Last edited by Salem; 04-17-2020 at 10:43 AM. Reason: Removed crayola

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,658
    > by 0x108BF0: add_country (projekti.c:16)
    The malloc you call here isn't freed.

    > free(array);
    You also need to free each array[i].name as well, before you free(array)
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Help with assignment (Olympic medals)
    By Olchi in forum C Programming
    Replies: 2
    Last Post: 04-06-2020, 06:19 AM
  2. Calculating Olympic medals
    By Shaun123 in forum C Programming
    Replies: 11
    Last Post: 04-17-2018, 03:28 AM
  3. need assistance with a valgrind error within clang
    By saldar05 in forum C Programming
    Replies: 2
    Last Post: 03-04-2013, 01:59 AM
  4. Valgrind error help
    By edishuman in forum C Programming
    Replies: 1
    Last Post: 11-12-2011, 03:37 PM
  5. valgrind error - still reachable
    By myle in forum C Programming
    Replies: 1
    Last Post: 04-19-2009, 08:57 PM

Tags for this Thread