Home > Net >  Grader Valgrind returning "Use of uninitialised value of size 8"
Grader Valgrind returning "Use of uninitialised value of size 8"

Time:03-04

I'm writing some functions for a poker game, running it with my input and debugging with Valgrind returns no errors, but when I run it through the course grader with their input using Valgrind, it returns this error message:

Grading at Wed 02 Mar 2022 10:45:38 PM UTC
Compiling your code
rm -f test poker cards.o my-test-main.o *~
cc -ggdb3 -Wall -Werror -pedantic -std=gnu99   -c -o deck.o deck.c
cc -ggdb3 -Wall -Werror -pedantic -std=gnu99   -c -o eval.o eval.c
cc -ggdb3 -Wall -Werror -pedantic -std=gnu99   -c -o cards.o cards.c
gcc -o test-eval -ggdb3 deck.o deck-c4.o eval-c4.o eval.o test-eval.o cards.o input.o future.o
Testcase 1: Trying hands with nothing  //<----- Poker hand with nothing special
Valgrind returned an error status
==220== Memcheck, a memory error detector
==220== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==220== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==220== Command: ./test-eval inp.1.txt
==220== Parent PID: 219
==220== 
==220== Use of uninitialised value of size 8
==220==    at 0x109419: print_hand (deck.c:12)
==220==    by 0x10B9C6: describe_hand (in /graderhome/work/c3prj2_eval/test-eval)
==220==    by 0x10BBBE: main (in /graderhome/work/c3prj2_eval/test-eval)
==220== 
==220== Use of uninitialised value of size 8
==220==    at 0x109419: print_hand (deck.c:12)
==220==    by 0x10B9C6: describe_hand (in /graderhome/work/c3prj2_eval/test-eval)
==220==    by 0x10BBE2: main (in /graderhome/work/c3prj2_eval/test-eval)
==220== 
==220== 
==220== HEAP SUMMARY:
==220==     in use at exit: 0 bytes in 0 blocks
==220==   total heap usage: 278 allocs, 278 frees, 14,160 bytes allocated
==220== 
==220== All heap blocks were freed -- no leaks are possible
==220== 
==220== Use --track-origins=yes to see where uninitialised values come from
==220== For lists of detected and suppressed errors, rerun with: -s
==220== ERROR SUMMARY: 10 errors from 2 contexts (suppressed: 0 from 0)

print_hand() is some code that I've written in past assignments ( within deck.c ) that complements the one I'm struggling with ( eval.c ), it just calls print_card() for each card in the hand:

void print_hand(deck_t * hand){
  for(int i = 0; i < hand->n_cards; i  ) {
    print_card(*hand->cards[i]);//Prints a card.  //<----Line 12 here!
    printf(" ");//Then a space.
  }
}

print_card() just receives a type card_t and prints it's card_t.value and card_t.suit as type char, for example: "As", "Qc", "6d". (A hand could be "Kd Kh Ks 9h 7c 7h 2h")

But I really don't think the error is coming from these codes I've written before, everything had to pass the grader for that assignment.
Even so I went back and initialized every variable as well as in the code of eval.c (where I presume the error is), even though they were not being dereferenced before being initialized with a value.
Everything still works as expected for me, but the grader system still returns the same error message using Valgrind.

I really don't understand why the error still persists.
Could you please give me some help with this?
Thank you very much in advance.

I'll post the code that I wrote for this assignment bellow ( eval.c ), is not that big of a code, but it's bigger than what I've seen here, so please let me know if I shouldn't post this here.

I should mention that all the structs, for example: card_t and deck_t, all function names, types and parameters were given to me, and their main calls these functions and the ones I've written in past assignments.

#include "eval.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

/*Return negative if card1 has higher value than card2
  and vice-versa for decreasing order.*/
int card_ptr_comp(const void * vp1, const void * vp2) {
  const card_t *const *cp1 = vp1;
  const card_t *const *cp2 = vp2;
  if((*cp1)->value == (*cp2)->value) {
    //Lower ranking == better.
    if((*cp1)->suit < (*cp2)->suit) return -1;
    if((*cp1)->suit > (*cp2)->suit) return 1;
    if((*cp1)->suit == (*cp2)->suit) return 0;
  }
  if((*cp1)->value != (*cp2)->value)return (*cp2)->value - (*cp1)->value;
  printf("\n card_ptr_comp: This shouldn't have happened. ");
  return 0;
}

//Checks if there is a flush in hand.
suit_t flush_suit(deck_t * hand) {
  assert(hand->n_cards > 0);
  int sp = 0, he = 0, di = 0, cl = 0;
  for(int i = 0; i < hand->n_cards; i  ) {
    switch((*hand->cards[i]).suit) {
    case SPADES:
      sp  ;
      break;
    case HEARTS:
      he  ;
      break;
    case DIAMONDS:
      di  ;
      break;
    case CLUBS:
      cl  ;
      break;
    default:
      printf("Card doesn't have a correct suit");
      break;
    }
  }
  /*Counts how many times each suit has appeared in the hand.
    If any is equal to 5, returns it, else, returns NUM_SUITS.*/
  if(sp >= 5) return SPADES;
  if(he >= 5) return HEARTS;
  if(di >= 5) return DIAMONDS;
  if(cl >= 5) return CLUBS;
  else return NUM_SUITS;
}

//Get the largest element in passed in array.
unsigned get_largest_element(unsigned * arr, size_t n) {
  int temp = 0;
  for(int i = 0; i < n; i  ) {
    if(arr[i] > temp) temp = arr[i];
  }
  return temp;
}

//Returns the lowest index of a pair or a 3 of a kind.
size_t get_match_index(unsigned * match_counts, size_t n,unsigned n_of_akind) {
  for(int i = 0; i < n; i  ) {
    if(n_of_akind == match_counts[i]) return i;
  }
  return EXIT_FAILURE;
}

//Finds secondary pair of cards in hand.
ssize_t  find_secondary_pair(deck_t * hand,
                 unsigned * match_counts,
                 size_t match_idx) {
  for(int i = 0; i < hand->n_cards; i  ) {
    if(match_counts[i] > 1 && (*hand->cards[i]).value != (*hand->cards[match_idx]).value) {
      return i;
    }
  }
  return -1; //Return -1 if nothing is found.
}

//Helper function to find index of 5 if the hand starts with an Ace
int where_5_at(deck_t * hand) {
  for(int i = 0; i < hand->n_cards; i  ) {
    if((*hand->cards[i]).value == 5) return i;
  }
  return -1;
}

//Helper function that looks for Straights.
int straight_helper(deck_t *hand, size_t index, suit_t fs) {
  int check = 1, dif = 0;
  card_t temp = *hand->cards[0];
  for(int i = index; i < hand->n_cards; i  ) {
    if(i == index) { //If first iteration, set temp to card at index.
      temp = *hand->cards[i];
      continue;
    }
    dif = temp.value - (*hand->cards[i]).value;
    if(dif == 0) continue; //If the value of both cards are the same, continue.
    if(dif == 1) { //If dif is 1, hand->cards[i] is adding to the Straight.
      check  ;
      if(check == 5) return 1; //If check is equal to 5, there is a Straight in hand.
      temp = *hand->cards[i];
      continue;
    }
    if(dif > 1) return 0; //If dif > 1, there is no Straight in the hand.
  }
  return 0;
}

//Helper function that looks for Straight Flushes.
int straightFlush_helper(deck_t *hand, size_t index, suit_t fs) {
  if((*hand->cards[index]).suit != fs) return 0;
  int check = 1, strike = 0, dif = 0;
  card_t temp = *hand->cards[0];
  for(int i = index; i < hand->n_cards; i  ) {
    if(i == index) { //If first iteration, set temp to card at index.
      temp = *hand->cards[i];
      continue;
    }
    dif = temp.value - (*hand->cards[i]).value;
    //If strike = 1.
    if(strike == 1) {
      if(dif == 1 && (*hand->cards[i]).suit == fs) { //If [i] suit is fs it adds to the Straight Flush.
    strike = 0;
    check  ;
    if(check == 5) return 1; //If check is equal to 5, there is a Straight in hand.
    temp = *hand->cards[i];
    continue;
      }
      if(dif == 1 && (*hand->cards[i]).suit != fs) {
    strike = 2;
    continue;
      }
      return 0;
    }
    if(strike == 2) { //If strike = 2.
      if(dif == 1 && (*hand->cards[i]).suit == fs) { //If [i] suit is fs it adds to the Straight Flush.
    strike = 0;
    check  ;
    if(check == 5) return 1; //If check is equal to 5, there is a Straight in hand.
    temp = *hand->cards[i];
    continue;
      }
      return 0;
    }
    //If strike = 0.
    if(dif == 0) continue; //If cards are the same, get next card.
    if(dif == 1 && (*hand->cards[i]).suit != fs) { /*If [i] is not Fs, the hand can still
                                                   contain a Straight Flush.*/
      strike = 1; //Sets strike to 1, so next card has to be the same value and suit == fs.
      continue;
    }
    if(dif == 1 && (*hand->cards[i]).suit == fs) { /*If dif is 1 and [i] is fs,
                                                   [i] is adding to the Straight Flush.*/
      check  ;
      if(check == 5) return 1; //If check is equal to 5, there is a Straight in hand.
      temp = *hand->cards[i];
      continue;
    }
    if(dif > 1) return 0; //If dif > 1, there is no Straight in the hand.
  }
  return 0;
}

//Helper function that looks for Ace-low Straights.
int ace_straight_helper(deck_t *hand, size_t index, suit_t fs) {
  if(where_5_at(hand) == -1) return 0;
  //check receives 2, because we have the Ace on index 0 or 1, and the 5.
  int check = 2, dif = 0;
  card_t temp = *hand->cards[where_5_at(hand)];
  for(int i = where_5_at(hand); i < hand->n_cards; i  ) {
    if(i == where_5_at(hand)) { //If first iteration, set temp to card at index of 5.
      temp = *hand->cards[i];
      continue;
    }
    dif = temp.value - (*hand->cards[i]).value;
    if(dif == 0) continue; //If value of both cards are the same, continue.
    if(dif == 1) { //If dif is 1, hand->cards[i] is adding to the Straight.
      check  ;
      if(check == 5) return -1; //If check is equal to 5, there is a Straight in hand.
      temp = *hand->cards[i];
      continue;
    }
    if(dif > 1) return 0; //If dif > 1, there is no Straight in the hand.
  }
  return 0;
}
  
//Helper function that looks for Ace-low Straight Flushes.
int ace_straightFlush_helper(deck_t *hand, size_t index, suit_t fs) {
  if((*hand->cards[index]).suit != fs) return 0;
  if(where_5_at(hand) == -1) return 0;
  if((*hand->cards[where_5_at(hand)]).suit != fs) return 0;
  //check receives 2, because we have the Ace on index 0 or 1, and the 5.
  int check = 2, strike = 0, dif = 0;
  card_t temp = *hand->cards[where_5_at(hand)];
  for(int i = where_5_at(hand); i < hand->n_cards; i  ) {
    if(i == where_5_at(hand)) { //If first iteration, set temp to card at index of 5.
      temp = *hand->cards[i];
      continue;
    }
    dif = temp.value - (*hand->cards[i]).value;
    //If strike = 1.
    if(strike == 1) {
      if(dif == 1 && (*hand->cards[i]).suit == fs) { /*If [i] suit is fs it adds
                                                     to the Straight Flush.*/
    strike = 0;
    check  ;
    if(check == 5) return -1; //If check is equal to 5, there is a Straight in hand.
    temp = *hand->cards[i];
    continue;
      }
      if(dif == 1 && (*hand->cards[i]).suit != fs) {
    strike = 2;
    continue;
      }
      return 0;
    }
    if(strike == 2) { //If strike = 2.
      if(dif == 1 && (*hand->cards[i]).suit == fs) { //If [i] suit is fs it adds to the Straight Flush.
    strike = 0;
    check  ;
    if(check == 5) return -1; //If check is equal to 5, there is a Straight in hand.
    temp = *hand->cards[i];
    continue;
      }
      return 0;
    }
    //If strike = 0.
    if(dif == 0) continue; //If cards are the same, get next card.
    if(dif == 1 && (*hand->cards[i]).suit != fs) { /*If [i] is not Fs, the hand can still
                                                   contain a Straight Flush.*/
      strike = 1; //Sets strike to 1, so next card, has to be the same value and suit = fs.
      continue;
    }
    if(dif == 1 && (*hand->cards[i]).suit == fs) { /*If dif is 1 and [i] is fs,
                                                   [i] is adding to the Straight Flush.*/
      check  ;
      if(check == 5) return -1; //If check is equal to 5, there is a Straight Flush in hand.
      temp = *hand->cards[i];
      continue;
    }
    if(dif > 1) return 0; //If dif > 1, [i] is not adding to the Straight Flush.
  }
  return 0;
}

//Uses helper functions to look for Straights and Straight flushes.
int is_straight_at(deck_t * hand, size_t index, suit_t fs) {
  assert(hand->n_cards > 0);
  //Ace-low Straight.
  if((*hand->cards[index]).value == VALUE_ACE && fs == NUM_SUITS) {
    if(straight_helper(hand, index, fs) == 0) {
      //If straigh_helper returns 0, It looks for an Ace-low Straight.
      return ace_straight_helper(hand, index, fs);
    }else{
      return 1;
    }
    //Ace-low Straight Flush.
  }else if((*hand->cards[index]).value == VALUE_ACE && fs != NUM_SUITS) {
    if(straightFlush_helper(hand, index, fs) == 0) {
      //If straighFlush_helper returns 0, It looks for an Ace-low Straight Flush.
      return ace_straightFlush_helper(hand, index, fs);
    }else{
      return 1;
    }
  }
  //Regular Straight.
  if((*hand->cards[index]).value != VALUE_ACE && fs == NUM_SUITS) {
    return straight_helper(hand, index, fs);
    //Straight Flush.
  }else if((*hand->cards[index]).value != VALUE_ACE && fs != NUM_SUITS) {
    return straightFlush_helper(hand, index, fs);
  }
  return 0;
}

//Builds a hand with a Pair, 3 of a kind or a Full House.
hand_eval_t build_hand_from_match(deck_t * hand,
                  unsigned n,
                  hand_ranking_t what,
                  size_t idx) {
  assert(hand->n_cards > 4);
  hand_eval_t ans;
  ans.ranking = what;
  int count = 0;
  //Copies 'n' cards starting at 'idx'.
  for(int i = idx; i < idx   n; i  ) {
    ans.cards[count] = hand->cards[i];
    count  ;
  }
  //Copies the rest of the highest cards into the array.
  for(int i = 0; i < 5; i  ) {
    if((*hand->cards[i]).value == (*hand->cards[idx]).value) continue;
    ans.cards[count] = hand->cards[i];
    count  ;
  }
  return ans;
}

//Sorts and compares two hands to get the winner.
int compare_hands(deck_t * hand1, deck_t * hand2) {
  //Sorts hand1 and hand2.
  qsort(hand1->cards, hand1->n_cards, sizeof(struct card_tag), card_ptr_comp);
  qsort(hand2->cards, hand2->n_cards, sizeof(struct card_tag), card_ptr_comp);
  
  //Compares the two hands.
  hand_eval_t cleanHand1 = evaluate_hand(hand1);
  hand_eval_t cleanHand2 = evaluate_hand(hand2);
  if(cleanHand1.ranking < cleanHand2.ranking) return 1;
  else if(cleanHand1.ranking > cleanHand2.ranking) return -1;
  else if(cleanHand1.ranking == cleanHand2.ranking) {
    int dif = 0;
    for(int i = 0; i < 5; i  ) {
      dif = cleanHand1.cards[i]->value - cleanHand2.cards[i]->value;
      if(dif > 0) return 1;
      if(dif < 0) return -1;
    }
    return 0;
  }
  printf("Something went wrong call 911 right now!");
  return 0;
}

CodePudding user response:

"Use of uninitialised value" means exactly what it says. In context of the line for which that message was reported, the uninitialized value must be that of *hand->cards[i] for some i. That the issue is recognized by valgrind probably means that that expression designates part of a dynamically allocated object. Note well that malloc() returns pointers to (formally) uninitialized memory.

I leave it to you to determine why the memory in question goes uninitialized in the case in question.

CodePudding user response:

Initialise the memory allocated using malloc with a call to memset, before operating on the allocated memory.

void* ptr = malloc(sizeof(hand));
memset(ptr, 0, sizeof(hand));
  • Related