释放记忆,全部?

Jas*_*n94 1 c

也许是一个糟糕的话题,但考虑到以下代码,我是否free(player->name)也需要呢?

#include <stdio.h>

struct Player
{
       char *name;
       int level;       
};

int main()
{
    struct Player *player;
    player->name = malloc(sizeof(player->name)*256);
    player->name = "John";

    printf(player->name);

    free(player);

    printf("\n\n\n");
    system("PAUSE");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

sbi*_*sbi 15

哦,小伙子,从哪里开始?你真的需要一本好书.叹.让我们从顶部开始main():


这个

struct Player *player;
Run Code Online (Sandbox Code Playgroud)

定义指向a的指针struct Player,但不初始化它.因此它具有或多或少的随机值,指向存储器中的某处.这个

player->name = malloc(sizeof(player->name)*256);
Run Code Online (Sandbox Code Playgroud)

现在将随机位置的一部分写入一块内存的地址malloc().通过未初始化的指针写入内存会调用未定义的行为.之后,所有赌注都已关闭.无需进一步了解您的计划.你不幸的是,你不小心写入了你的进程所拥有的一块内存,所以它不会立即崩溃,让你意识到这个问题.

有两种方法可以改善它.要么坚持指针并让它指向为Player对象分配的一块内存.你可以通过电话获得它malloc(sizeof(Player).
或者只使用本地的自动(也称为基于堆栈)对象:

struct Player player;
Run Code Online (Sandbox Code Playgroud)

编译器将生成代码以在堆栈上为其分配内存并自动释放它.这是最简单的,当然应该是你的默认值.


但是,您的代码有更多问题.

这个

player->name = malloc(sizeof(player->name)*256);
Run Code Online (Sandbox Code Playgroud)

在堆上分配连续内存以存储256个指向字符的指针,并将第一个指针的地址(a的地址char*,因此a char**)分配给player->name(a char*).坦率地说,我很惊讶甚至编译,但后来我更习惯于C++更严格的类型执行.无论如何,你可能想要的是为256个字符分配内存:

player->name = malloc(sizeof(char)*256);
Run Code Online (Sandbox Code Playgroud)

(sizeof(char)根据定义,1你会经常看到这个malloc(256).)
但是,更多的是:为什么256?如果我将字符串传递1000个字符怎么办?不,简单地为更长的字符串分配空间不是解决这个问题的方法,因为我可以将它传递给更长的字符串.因此要么1)修复最大字符串长度(只是声明为该长度Player::namechar数组,而不是a char*)并在代码中强制执行此限制,或者2)在运行时动态找出所需的长度,并准确分配所需的内存(字符串长度加1,终止'\0'字符).

但它变得更糟.这个

player->name = "John";
Run Code Online (Sandbox Code Playgroud)

然后分配一个字符串文字player->name的地址,覆盖malloc()你存储它的唯一变量所分配的内存地址,使你丢失并泄漏内存.
但是字符串在C中不是一等公民,所以你不能分配它们.它们是字符数组,按惯例终止于'\0'.要复制它们,您必须逐个字符地复制它们,或者循环,或者最好通过调用strcpy().

为了增加对伤害的侮辱,你后来试图释放一个字符串文字所在的记忆

free(player);
Run Code Online (Sandbox Code Playgroud)

因此很可能严重扰乱堆管理器的数据结构.再一次,你似乎不幸的是不会导致立即崩溃,但看似按预期工作的代码是未定义行为表现出来的最糟糕的可能性之一.如果以前所有赌注都没有被淘汰,他们现在就会完全失败.


我很抱歉,如果这听起来很谴责,那真的不是那种意思,但是你肯定并且认真地搞砸了这个.包装它:

  1. 你需要一本好的C++书.马上.以下是C程序员在Stack Overflow上汇编的好书清单.(我是一名C++程序员,所以我不会评论他们的判断,但K&R肯定是一个不错的选择.)

  2. 您应该立即初始化所有指针,或者使用现有有效对象的地址,或者使用分配用于保存正确类型的对象的内存的地址,或者使用NULL(您可以在以后轻松检查).特别是,您不得尝试读取或写入尚未分配(在堆上动态或在堆栈上自动分配)的内存.

  3. 你需要free()通过调用malloc() 一次获得的所有内存.

  4. 你不能尝试free()任何其他记忆.


我确信那段代码还有更多,但我会在这里停下来.我是否提到你需要一本好的C书?因为你这样做.