Reputation: 1
#include "card.h"
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int comparator(const void *a, const void *b)
{
card_t *carda = *(card_t **)a;
card_t *cardb = *(card_t **)b;
return strcmp(carda->name, cardb->name);
free(carda);
free(cardb);
}
int main(int argc, char **argv) {
int num_entries = 0;
card_t **cards = NULL;
int freeCards = 0;
char *buf = NULL;
size_t bufsiz = 0;
int same = 0;
//char *tempChar;
int x = 0;
FILE *input_file = fopen(argv[1], "r");
ssize_t result;
getline(&buf, &bufsiz, input_file);
while ( (result = getline(&buf, &bufsiz, input_file)) > 0){
num_entries++;
cards = realloc(cards, sizeof(card_t *) * num_entries);
cards[x] = malloc(sizeof(card_t));
char *stringp = buf;
char *textCopy = strdup(buf);
int tempInt = atoi(strsep(&stringp, ","));
same = 0;
freeCards = 0;
while (freeCards < num_entries){
if (cards[freeCards]->id == tempInt){
same = 1;
free(cards[x]);
free(textCopy);
num_entries--;
}
freeCards++;
}
stringp++;
char *sameName = strdup(strsep(&stringp, "\""));
while (freeCards < num_entries){
if (strcmp (cards[freeCards]->name, sameName)== 0){
if (cards[freeCards]->id > tempInt){
same = 1;
free(cards[x]);
free(textCopy);
num_entries--;
}
else{
cards[freeCards]->id = tempInt;
same = 1;
free(cards[x]);
free(textCopy);
num_entries--;
}
}
freeCards++;
}
if (same == 0){
cards[x]->id = tempInt;
//get name
cards[x]->name = sameName;
//get cost
stringp += 2;
cards[x]->cost = strdup(strsep(&stringp, "\""));
//converted_cost
stringp++;
cards[x]->converted_cost = atoi(strsep(&stringp, "\""));
//type
cards[x]->type = strdup(strsep(&stringp, "\""));
//text
stringp+=2;
cards[x]->text = strdup(strsep(&stringp, "\""));
//textLenght =strlen(stringp);
//strsep(&stringp, "\"");
//stats
//afterTextLenght =strlen(stringp);
stringp+= 2;
cards[x]->stats = strdup(strsep(&stringp, "\""));
//rarity
stringp+= 2;
char *testRare = strsep(&stringp, "\"");
if (strcmp ("common", testRare)== 0){
cards[x]->rarity = 0;
}else if (strcmp ("uncommon",testRare) == 0){
cards[x]->rarity = 1;
}else if (strcmp ("re",testRare) == 0){
cards[x]->rarity = 2;
}else{
cards[x]->rarity = 3;
}
//printf("%ld====\n",result);
//strncpy(textCopy, textCopy +(startLength-textLenght), (textLenght-afterTextLenght));
//cards[x]->text = strdup(textCopy);
free(textCopy);
x++;
}
}
//qsort( cards, num_entries, sizeof(card_t *), comparator);
freeCards = 0;
while (freeCards < num_entries){
printf("%-43s%s\n----------------------------------------------------\n",cards[freeCards]->name,cards[freeCards]->cost);
if (cards[freeCards]->rarity == 0){
printf("%-45s common\n----------------------------------------------------\n",cards[freeCards]->type);
}else if(cards[freeCards]->rarity == 1){
printf("%-43s uncommon\n----------------------------------------------------\n",cards[freeCards]->type);
}else if (cards[freeCards]->rarity == 2){
printf("%-47s rare\n----------------------------------------------------\n",cards[freeCards]->type);
}else{
printf("%-45s mythic\n----------------------------------------------------\n",cards[freeCards]->type);
}
printf("%s\n",cards[freeCards]->text);
printf("----------------------------------------------------\n");
printf("%52s\n",cards[freeCards]->stats);
freeCards++;
}
freeCards = 0;
while (freeCards < num_entries){
free(cards[freeCards]->name);
free(cards[freeCards]->cost);
free(cards[freeCards]->type);
free(cards[freeCards]->text);
free(cards[freeCards]->stats);
free(cards[freeCards]);
freeCards++;
}
free(cards);
free(buf);
fclose(input_file);
return 0;
}
enum rarity
{
common,
uncommon,
rare,
mythic
};
typedef struct card
{
unsigned int id;
char* name;
char* cost;
unsigned int converted_cost;
char* type;
char* text;
char* stats;
enum rarity rarity;
} card_t;
make && valgrind -q --leak-check=yes ./parser short-cards-1.csv
make: 'parser' is up to date.
==24945== Conditional jump or move depends on uninitialised value(s)
==24945== at 0x108B2B: main (in /home/brandon/cs3240_system_programming_concepts_spring_2021/a1_mtg_card_data_parsing/parser)
==24945==
Stolen by the Fae {X}{U}{U}
----------------------------------------------------
Sorcery rare
----------------------------------------------------
Return target creature with converted mana cost X to its owner's hand. You create X 1/1 blue Faerie creature tokens with flying.
----------------------------------------------------
Eternal Isolation {1}{W}
----------------------------------------------------
Sorcery common
----------------------------------------------------
Put target creature with power 4 or greater on the bottom of its owner's library.
----------------------------------------------------
Corpse Knight {W}{B}
----------------------------------------------------
Creature - Zombie Knight uncommon
----------------------------------------------------
Whenever another creature enters the battlefield under your control, each opponent loses 1 life.
----------------------------------------------------
2/2
Orzhov Enforcer {1}{B}
----------------------------------------------------
Creature - Human Rogue uncommon
----------------------------------------------------
Deathtouch\nAfterlife 1 (When this creature dies, create a 1/1 white and black Spirit creature token with flying.)
----------------------------------------------------
1/2
==24945== 18 bytes in 1 blocks are definitely lost in loss record 1 of 1
==24945== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==24945== by 0x4ED99B9: strdup (strdup.c:42)
==24945== by 0x108B95: main (in /home/brandon/cs3240_system_programming_concepts_spring_2021/a1_mtg_card_data_parsing/parser)
So I'm not sure why valgrind is telling me my leak is at line 42 (strdup.c:42
). I've tried going through my code myself and cant find where the leak is. so I was hoping valgrind would help but last I checked I don't need to free a statement that looks like freeCards = 0
.
To clear thing up the point of the code is to take a CSV file and split it into a struct and sort it. I have everything working but can't find this memory leak.
Upvotes: 0
Views: 140
Reputation: 69367
What Valgrind is telling you is that your main
function is calling strdup()
and that you are not freeing the pointer returned by strdup()
afterwards. It then goes into more detail telling you that inside strdup the memory was allocated using malloc()
, and points you to the line of the C library source code (not your code) which defines strdup()
and does the actual call to malloc()
. This is because you have the debugging symbols installed for the C library you're using (most likely glibc
).
You do not care about any of this. You want to know where in your main
is the offending strdup()
call that causes a leak. In order to make Valgrind able to show you line number information for your own program, you must compile it with debugging information, which can be done for GCC/Clang using the -g
compilation flag (e.g. gcc -g prog.c -o prog
). After doing this and running Valgrind again, you will be able to see Valgrind point out which line of main
is responsible for that call to strdup()
.
Upvotes: 3