首页 > 解决方案 > 使用 free() 释放内存使整个 C 程序不打印任何分配的数据?

问题描述

C中的指针对我来说是一个非常困难的主题。这是我作业中代码的一部分,它重现了我遇到的问题。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <crtdbg.h>

#define MAX_SONGS_PER_USER   10
#define MAX_USERS             5
#define MAX_ARTISTS         100


#define NUM_TEST_USERS      7


// This struct represents a song in the system
typedef struct {
    char      *title;
    char      *artist;
    short int  duration;
    char        downloaded;
} Song;

// This struct represents a user in the system
typedef struct {
    char       *name;
    char        online;                    // 1 = YES, 0 = NO
    Song       *songs[MAX_SONGS_PER_USER]; // songs this user has
    short int   numSongs;                  // number of songs this user has
} User;

// This structure represents the Tune Share system
typedef struct {
    User        *users[MAX_USERS];     // An array of all registered users
    short int    numUsers;
} TuneShare;

int registerUser(TuneShare *t, char *name)
{
    short int numUsers = t->numUsers;

    if (numUsers == MAX_USERS)
    {
        return 0;
    }
    else
    {
        if(numUsers >= 1)
            //printf("%s \n", t->users[0]->name);
        for (int i = 0; i < numUsers; i++)
        {
            User *u = t->users[i];
            char *uName = u->name;
            if (uName == name)
            {
                return 0;
            }
            //free(u);
        }
        User *temp;
        if ((temp = malloc(sizeof *temp)) != NULL)
        {
            temp->name = name;
            temp->numSongs = 0;
            temp->online = '0';
        }
        
        t->users[numUsers] = temp;

        t->numUsers = numUsers + 1;

        return 1;
    }
}

int addSong(User *u, char *title, char *artist, short int duration)
{
    short int numSongs = u->numSongs;
    if (numSongs == MAX_SONGS_PER_USER)
    {
        return 0;
    }
    else
    {
        if (numSongs >= 1)
            for (int i = 0; i < numSongs; i++)
            {
                if (u->songs[i]->title == title)
                {
                    return 0;
                }
            }
        Song *temp;
        if ((temp = malloc(sizeof *temp)) != NULL)
        {
            temp->title = title;
            temp->artist = artist;
            temp->duration = duration;
        }
        u->songs[numSongs] = temp;
        u->numSongs = numSongs + 1;
        //free(temp);
        return 1;
    }
}

void logon(TuneShare *t, char *name)
{
    User *u = userWithName(t, name);
    
    if (u != NULL)
    {
        u->online = '1';
    }
}

void displayStats(TuneShare *t)
{
    printf("\nTune Share Center (%d registered users)\n", t->numUsers);
    short int numOnline = 0, numSongs = 0;
    User **u = onlineUsers(t, &numOnline);
    Song **s = allAvailableSongs(t, &numSongs);


    printf("\n%d Online Users:\n", numOnline);
    if (numOnline == 0)
    {
        printf("\tNONE\n\n");
    }
    else
    {
        for (int i = 0; i < numOnline; i++)
        {
            printf("\t%s with %d songs as follows:\n", u[i]->name, u[i]->numSongs);
            for (int j = 0; j < u[i]->numSongs; j++)
            {
                printf("\t\t\"%s\" by %s\n", u[i]->songs[j]->title, u[i]->songs[j]->artist);
            }
        }
    }

    printf("\n%d Available Songs:\n", numSongs);
    if (numSongs == 0)
    {
        printf("\tNONE\n\n");
    }
    else
    {
        for (int i = 0; i < numSongs; i++)
        {           
            int min = s[i]->duration / 60;
            int sec = s[i]->duration % 60;
            if(sec > 10)
                printf("\t\"%s\" by %s (%d:%d)\n", s[i]->title, s[i]->artist, min, sec);
            else
                printf("\t\"%s\" by %s (%d:0%d)\n", s[i]->title, s[i]->artist, min, sec);
        }
    }
    printf("\n");
}


int main() {
    // This is test data
    static char *TITLES[] = { "Back 2 Life", "Loneliness For Love", "Desire 126", "Perfect", "In My Head",
                             "Old Skool Love", "Let's Go", "No Place", "We Gotta Go", "How You Get the Girl",
                             "Catch", "Here Tonight", "Details", "Dangerous", "Brighter Than the Sun",
                             "Photograph", "Thinking Out Loud", "If Heaven Were to Fall", "I Just Wanna Be With You",
                             "Song Sung Blue", "Outta Style", "Why", };

    static char *ARTISTS[] = { "E-Type", "Lovely the Band", "Hollerado", "Ed Sheeran", "Ryland James",
                              "Divine Brown", "Group 1 Crew", "Backstreet Boys", "E-Type", "Taylor Swift",
                              "Brett Young", "Brett Young", "Billy Currington", "Kardinal Offichall",
                              "Colbie Caillat", "Ed Sheeran", "Ed Sheeran", "E-Type", "E-Type", "Neil Diamond",
                              "Aaron Watson", "Frankie Avalon", };

    static int   DURATIONS[] = { 217, 237, 187, 263, 205, 204, 256, 179, 213, 247, 196,
                                216, 201, 251, 231, 202, 281, 223, 230, 185, 222, 161 };


    static char *TEST_USER_NAMES[NUM_TEST_USERS] = { "Disco Stew", "Peter Punk", "Country Candy", "Ronnie Rocker",
                                                    "Sleeping Sam", "Disco Stew", "Mellow Marvin" };

    static int  LIST_SIZES[NUM_TEST_USERS] = { 7, 9, 9, 5, 1, 0, 0 };
    static int  SONGNUMS[NUM_TEST_USERS][MAX_SONGS_PER_USER] = {
                                   {1, 2, 4, 5, 12, 15, 21}, {0, 1, 3, 8, 9, 13, 14, 17, 20},
                                   {6, 7, 8, 10, 11, 12, 13, 20, 21}, {0, 8, 16, 17, 18}, {19}, {0}, {0} };


    // Create the TuneShare Center
    TuneShare   tuneShareCenter;
    tuneShareCenter.numUsers = 0;

    // Attempt to register all test users
    for (int i = 0; i < NUM_TEST_USERS; i++) {
        if (!registerUser(&tuneShareCenter, TEST_USER_NAMES[i]))
            printf("Error adding User: \"%s\"\n", TEST_USER_NAMES[i]);
        else
            printf("User: \"%s\" has been registered\n", TEST_USER_NAMES[i]);
    }
    
    // Display some stats
    displayStats(&tuneShareCenter);

    // Log on a user
    printf("\nLogging on a user...\n");
    logon(&tuneShareCenter, "Disco Stew");
    // Display some stats
    displayStats(&tuneShareCenter);

    // Now add all the test songs for these test users
    for (int i = 0; i < tuneShareCenter.numUsers; i++) {
        for (int j = 0; j < LIST_SIZES[i]; j++)
            addSong(tuneShareCenter.users[i], TITLES[SONGNUMS[i][j]], ARTISTS[SONGNUMS[i][j]], DURATIONS[SONGNUMS[i][j]]);
    }
    
    // Display some stats
    displayStats(&tuneShareCenter);

}

这给出了我需要的正确输出。像这样。 正确输出

但是,当我使用free()函数作为函数 **int registerUser(TuneShare t, char name)中的示例从堆中释放分配的内存时,它根本没有给出输出,

int registerUser(TuneShare *t, char *name)
{
    short int numUsers = t->numUsers;

    if (numUsers == MAX_USERS)
    {
        return 0;
    }
    else
    {
        if(numUsers >= 1)
            //printf("%s \n", t->users[0]->name);
        for (int i = 0; i < numUsers; i++)
        {
            User *u = t->users[i];
            char *uName = u->name;
            if (uName == name)
            {
                return 0;
            }
            //free(u);
        }
        User *temp;
        if ((temp = malloc(sizeof *temp)) != NULL)
        {
            temp->name = name;
            temp->numSongs = 0;
            temp->online = '0';
        }
        
        t->users[numUsers] = temp;

        t->numUsers = numUsers + 1;
        free(temp);
        return 1;
    }

}

这是我使用上面的free()时的输出。

在此处输入图像描述

我不明白是什么问题。如果有人可以帮助我,那就太棒了。

标签: cpointersstructmallocfree

解决方案


您可能会误解的问题是调用free(temp)会释放内存中指向的对象- 它与变量本身 temp没有任何关系。一旦函数返回,将被释放。事实上,声明自己甚至可能是不必要的。temptemptemp

int registerUser(TuneShare *t, char *name)
{
    int i;

    if (t->numUsers >= MAX_USERS)
        return 0;

    for (i = 0; i < t->numUsers; i++)
        if (strcmp(t->users[i]->name, name) == 0)
            return 0;

    if ((t->users[t->numUsers] = malloc(sizeof User)) == NULL)
        return 0;

    t->users[t->numUsers]->name = name;
    t->users[t->numUsers]->numSongs = 0;
    t->users[t->numUsers]->online = '0';    

    t->numUsers++;
    
    return 1;
}

推荐阅读