| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 705 人关注过本帖
标题:我给一程序加上Free就错了。。。。
只看楼主 加入收藏
列车永不停息
Rank: 2
等 级:论坛游民
帖 子:76
专家分:48
注 册:2015-7-31
结帖率:90.91%
收藏
已结贴  问题点数:50 回复次数:9 
我给一程序加上Free就错了。。。。
程序如下:
程序代码:
#include "stdafx.h"
#include <cstdio>
#include <cstdlib>
#include <conio.h>

struct Student
{
    char Name[11];
    char Sex;
    long Birthday;
    Student* next;
};

void Init(void);
void Save_Data(const char* filename, Student* students, size_t count);
Student* Load_Data(const char* filename);
void Update_Data(const char* filename, const Student* student, size_t index);
void List_Students(Student* students);
void Show_Student(const Student* student);
void free_shuju(Student* head);
const char* FileName = "Students.DAT";

int main(void)
{
    Init();

    Student* students = Load_Data(FileName);
    List_Students(students);

    printf_s("Now update record 2\n");
    students->next->Birthday = 19921014;
    students->next->Sex = 0;
    Update_Data(FileName, students->next, 2);    // 用指针students-next所指向的数据,刷写文件中的第2条记录
    students = Load_Data(FileName);
    List_Students(students);
    free_shuju(students);
    printf_s("\nPress any key to continue...");
    _getch();
    return EXIT_SUCCESS;
}

void Init(void)
{
    Student students[3] = {
        { "张三", 0, 19920312 },
        { "李四", 1, 19921004 },
        { "王五", 0, 19930120 }
    };
    Save_Data(FileName, students, _countof(students));
}

void Save_Data(const char* filename, Student* students, size_t count)
{
    FILE* file;

    if (fopen_s(&file, filename, "wb") == 0)
    {
        fwrite(&count, sizeof(count), 1, file);
        for (size_t index = 0; index < count; ++index)
        {
            fwrite(&students[index], sizeof(Student), 1, file);
        }
        fclose(file);
    }
    else
    {
        printf_s("File %s create failure.\n", filename);
    }
}

Student* Load_Data(const char* filename)
{
    FILE* file;
    Student* head = NULL;

    if (fopen_s(&file, filename, "rb") == 0)
    {
        size_t count;
        Student* previous = NULL;
        fread(&count, sizeof(count), 1, file);
        for (size_t index = 0; index < count; ++index)
        {
            Student* stu = (Student*)calloc(1, sizeof(Student));
            if (stu != NULL)
            {
                (previous != NULL) ? (previous->next = stu) : (head = stu);
                fread(stu, sizeof(Student), 1, file);
                previous = stu;
            }
            else
            {
                printf_s("Memory allocation error.\n");
                break;
            }
        }
        fclose(file);
    }
    else
    {
        printf_s("File %s read failure.\n", filename);
    }

    return head;
}

void Update_Data(const char* filename, const Student* student, size_t index)
{
    FILE* file;

    if (fopen_s(&file, filename, "rb+") == 0)
    {
        size_t count;
        fread(&count, sizeof(count), 1, file);
        fseek(file, (index - 1) * sizeof(Student), SEEK_CUR);
        fwrite(student, sizeof(Student), 1, file);
        fclose(file);
    }
    else
    {
        printf_s("File %s update failure.\n", filename);
    }
}

void List_Students(Student* students)
{
    while (students != NULL)
    {
        Show_Student(students);
        students = students->next;
    }
}

void Show_Student(const Student* student)
{
    printf_s("%-10s   %2s   %u\n", student->Name, (student->Sex == 0) ? "" : "", student->Birthday);
}

void free_shuju(Student* head)
{
   if(head!=NULL)
   {
      Student* sf;
      sf=head;
     do
     {
       free(sf);
       sf=sf->next;
     }while(sf!=NULL);
   }
}


调试之后出现这样的情况:
图片附件: 游客没有浏览图片的权限,请 登录注册
2015-08-07 20:45
hjx1120
Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15
来 自:李掌柜
等 级:贵宾
威 望:41
帖 子:1314
专家分:6927
注 册:2008-1-3
收藏
得分:0 
楼主写的是c++,发的问题却在c,男人女人虽然都是人,可正常人第一眼就能分清谁是男人谁是女人,难道楼主分不清楚c和c++
2015-08-07 21:36
列车永不停息
Rank: 2
等 级:论坛游民
帖 子:76
专家分:48
注 册:2015-7-31
收藏
得分:0 
回复 2楼 hjx1120
我建的文件是CPP啊,运行之后就自动跳出来个C文件出来。
2015-08-08 02:33
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
程序代码:
void free_shuju(Student* head)

 {
    if(head!=NULL)
    {
       Student* sf;
       sf=head;
      do
      {
        free(sf);            // 這裡釋放了指針sf所指向的對象
        sf=sf->next;         // 這裡右邊的sf是上面已經釋放過對象的sf,也就是說,你使用了已經失效的指針!
      }while(sf!=NULL);
    }

 }

授人以渔,不授人以鱼。
2015-08-08 10:14
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
你看我教程中的代碼是怎麼做的:

程序代码:
// 刪除並釋放從指定節點開始的鏈表數據
void FreeLink(Node* head)

 {
     if (head != NULL)
     {
         Node* next;                        // 聲明一個臨時指針,命名為next,則此指針的用途是指向鏈表下一個結點的
         do
         {
             next = head->Next;             // 預先取得下一個結點,因為當前結點被釋放後,將無法再通過結點的next指針得到下一個結點,故須先提取
             free(head);                    // 現在釋放當前的結點
             head = NULL;                   // 釋放結點後,記得把指向這個對象的指針复位為空指針,避免誤用
             head = next;                   // 把當前指針置為上面提取出來的下一個結點指針
         } while (next != NULL);
     }

 }


比較一下你的版本和我的版本,很容易看出區別了:我的是先得到next後free,而你的次序的反過來,先free後取next。那正是指針的陷阱,使用失效指針。在函數中返回指向局部變量的指針,即屬此類錯誤,書上有講不要返回如此這般指針的,道理就在這裡。

[ 本帖最后由 TonyDeng 于 2015-8-8 10:45 编辑 ]

授人以渔,不授人以鱼。
2015-08-08 10:23
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:50 
你比較一下我修改後的代碼,改動了什麼?想想為什麼要這麼改?

程序代码:
#include <cstdio>
#include <cstdlib>
#include <conio.h>

struct Student
{
    char Name[11];
    char Sex;
    long Birthday;
    Student* next;
};

void Init(void);
void Save_Data(const char* filename, Student* students, size_t count);
Student* Load_Data(const char* filename);
void Update_Data(const char* filename, const Student* student, size_t index);
void List_Students(Student* students);
void Show_Student(const Student* student);
void FreeLink(Student* head);

const char* FileName = "Students.DAT";

int main(void)
{
    Init();

    Student* students = Load_Data(FileName);
    List_Students(students);

    printf_s("Now update record 2\n");
    students->next->Birthday = 19921014;
    students->next->Sex = 0;
    Update_Data(FileName, students->next, 2);
    FreeLink(students);
    students = Load_Data(FileName);
    List_Students(students);
    FreeLink(students);

    printf_s("\nPress any key to continue...");
    _getch();
    return EXIT_SUCCESS;
}

void Init(void)
{
    Student students[3] = {
        { "张三", 0, 19920312 },
        { "李四", 1, 19921004 },
        { "王五", 0, 19930120 }
    };
    Save_Data(FileName, students, _countof(students));
}

void Save_Data(const char* filename, Student* students, size_t count)
{
    FILE* file;

    if (fopen_s(&file, filename, "wb") == 0)
    {
        fwrite(&count, sizeof(count), 1, file);
        for (size_t index = 0; index < count; ++index)
        {
            fwrite(&students[index], sizeof(Student), 1, file);
        }
        fclose(file);
    }
    else
    {
        printf_s("File %s create failure.\n", filename);
    }
}

Student* Load_Data(const char* filename)
{
    FILE* file;
    Student* head = NULL;

    if (fopen_s(&file, filename, "rb") == 0)
    {
        size_t count;
        Student* previous = NULL;
        fread(&count, sizeof(count), 1, file);
        for (size_t index = 0; index < count; ++index)
        {
            Student* stu = (Student*)calloc(1, sizeof(Student));
            if (stu != NULL)
            {
                (previous != NULL) ? (previous->next = stu) : (head = stu);
                fread(stu, sizeof(Student), 1, file);
                previous = stu;
            }
            else
            {
                printf_s("Memory allocation error.\n");
                break;
            }
        }
        fclose(file);
    }
    else
    {
        printf_s("File %s read failure.\n", filename);
    }

    return head;
}

void Update_Data(const char* filename, const Student* student, size_t index)
{
    FILE* file;

    if (fopen_s(&file, filename, "rb+") == 0)
    {
        size_t count;
        fread(&count, sizeof(count), 1, file);
        fseek(file, (index - 1) * sizeof(Student), SEEK_CUR);
        fwrite(student, sizeof(Student), 1, file);
        fclose(file);
    }
    else
    {
        printf_s("File %s update failure.\n", filename);
    }
}

void List_Students(Student* students)
{
    while (students != NULL)
    {
        Show_Student(students);
        students = students->next;
    }
}

void Show_Student(const Student* student)
{
    printf_s("%-10s   %2s   %u\n", student->Name, (student->Sex == 0) ? "" : "", student->Birthday);
}

void FreeLink(Student* head)
{
    if (head != NULL)
    {
        Student* next;
        do
        {
            next = head->next;
            free(head);
            head = NULL;
            head = next;
        } while (next != NULL);
    }
}

授人以渔,不授人以鱼。
2015-08-08 10:28
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
這是再正常不過的C代碼。C和C++的區別是思想,不是語法形式。使用cstdio、cstdlib之類帶c前綴的頭文件名,那是C++標準庫約定是C版本頭,C++版本的頭是沒有c前綴的。

授人以渔,不授人以鱼。
2015-08-08 10:39
列车永不停息
Rank: 2
等 级:论坛游民
帖 子:76
专家分:48
注 册:2015-7-31
收藏
得分:0 
回复 6楼 TonyDeng
可能是我编译器的问题,你给我的程序我去编译,会cstdio,cstdlib两个页面,然后一大堆错误在里面报错。
我用VS2010,建立C文件,建立的过程应该是对的。纳闷中。。。。。
图片附件: 游客没有浏览图片的权限,请 登录注册


[ 本帖最后由 列车永不停息 于 2015-8-8 20:47 编辑 ]
2015-08-08 20:44
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
建立.cpp文件

授人以渔,不授人以鱼。
2015-08-08 21:13
墨轩在路上
Rank: 2
等 级:论坛游民
帖 子:13
专家分:17
注 册:2015-8-14
收藏
得分:0 
语言混用啦!!!
2015-08-14 03:11
快速回复:我给一程序加上Free就错了。。。。
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.023314 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved