问题描述
#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,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)
所以我不知道为什么 valgrind 告诉我我的泄漏是在第 42 行 (strdup.c:42
)。我试过自己检查我的代码,但找不到泄漏的地方。所以我希望 valgrind 会有所帮助,但最后我检查了我不需要释放看起来像 freeCards = 0
的语句。
为了弄清楚代码的重点是获取一个 CSV 文件并将其拆分为一个结构体并对其进行排序。我一切正常,但找不到这个内存泄漏。
解决方法
Valgrind 告诉您的是您的 main
函数正在调用 strdup()
并且您没有释放 strdup()
之后返回的指针。然后它会更详细地告诉您 在 strdup 内部 内存是使用 malloc()
分配的,并指向C 库源代码行代码(不是您的代码),它定义了 strdup()
并实际调用了 malloc()
。这是因为您为正在使用的 C 库安装了调试符号(很可能是 glibc
)。
你不在乎这些。您想知道在您的 main
中哪个位置是导致泄漏的有问题的 strdup()
调用。为了使 Valgrind 能够向您显示您自己的程序的行号信息,您必须使用调试信息对其进行编译,这可以使用 -g
编译标志为 GCC/Clang 完成(例如gcc -g prog.c -o prog
)。执行此操作并再次运行 Valgrind 后,您将能够看到 Valgrind 指出 main
的哪一行负责对 strdup()
的调用。