微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么 valgrind 为我的内存泄漏提供了错误的行位置?

如何解决为什么 valgrind 为我的内存泄漏提供了错误的行位置?

#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() 的调用。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。