解除分配的记忆功能C

时间:2016-12-14 20:15:51

标签: c pointers malloc free

我在C中存在内存释放问题。没有功能划分,一切都很好,但不幸的是它不能用于相同的功能。这是代码:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef struct {
    char *name;
    enum {
        summer,
        winter
    } index;
} student;

bool init(student *s) {
    printf("The next stage in the allocation of memory\n");
    s = (student*)malloc(sizeof(*s));
    if (&s == NULL) {
        printf("Allocation Failed\n");
        return 0;
    } else {
        printf("Allocation completed successfully\n");
    }
}   

void delete(student *s) {
    if (&s != NULL) {
        printf("begin removal\n");
        free(s);
        printf("Released memory");
    }
}

int main() {
    student *s;
    init(s);
    delete(s);

    return 0;
}

我不知道我做错了什么。请帮忙。

3 个答案:

答案 0 :(得分:1)

首先,函数init具有未定义的bbehaviour,因为在成功分配内存的情况下它不会返回任何内容。

您可以通过返回指向已分配内存的指针或NULL来检查内存是否已分配。

此声明

if(&s==NULL){

错了。条件总是会产生错误,因为局部变量s的地址不等于NULL

因此可以通过以下方式重写该函数

student * init()
{
    printf("The next stage in the allocation of memory\n");

    student *s = ( student* )malloc( sizeof( *s ) );

    if ( s == NULL )
    {
        printf("Allocation Failed\n");
    } 
    else 
    {
        printf("Allocation completed successfully\n");
    }

    return s;
} 

并称之为

int main( void )
          ^^^^^
{
    student *s = init();
    //...

或者可以通过以下方式定义

int init( student **s )
{
    printf("The next stage in the allocation of memory\n");

    *s = ( student* )malloc( sizeof( **s ) );

    int success = *s != NULL;

    if ( !success )
    {
        printf("Allocation Failed\n");
    } 
    else 
    {
        printf("Allocation completed successfully\n");
    }

    return success;
} 

并调用

int main( void )
          ^^^^^
{
    student *s;
    init( &s );
    //...

函数delete应至少定义为

void delete(student *s) {
    if (s != NULL) {
       ^^^
        printf("begin removal\n");
        free(s);
        printf("Released memory");
    }
}

答案 1 :(得分:0)

首先,free是NULL安全的。如果变量已经是NULL,基本上没有任何反应。您不必检查它是否为NULL。 (您可以查看第313页ISO-IEC 9899

此外,初始化student->name并分配时,会出现内存泄漏。你也必须释放它。

所以,你的删除功能可能是这样的;

  void delete(student *s) {
    printf("begin removal\n");
    free(s->name);
    free(s);
    printf("Released memory");
}

if (&s == NULL)错了。必须使用if (s == NULL)更改它们。

你的分配可能会给大代码带来很大的麻烦。如果您分配s = (student*)malloc(sizeof(*s));,则表示&#34;分配大小为* s&#34;的s。但是指针大小是固定的内存块(大多是8个字节)。这意味着您阻止了一定大小的内存。如果你有比这更大的结构,这种分配将破坏内存,你的可执行文件将被操作系统杀死(你可以尝试在你的结构中添加更多的变量并初始化它们)。在小结构和非常短的运行时间中,大多数这种分配也有效。但我保证这对于运行时来说是不安全的。它不会在编译时发出任何警告或错误。真正的方式是s = malloc(sizeof(student))。通过这种方式,您可以精确地分配所有内存块。并且您的记忆在运行时保持安全。

最后,您的init函数应该返回初始化变量。你的init函数可能是这样的;

#define NAME_LENGHT 128

...

student * init(student *s) {
   printf("The next stage in the allocation of memory\n");
   s = malloc(sizeof(student));
   if (s == NULL) {
       printf("Allocation Failed\n");
       return NULL;
   }

   s->name = malloc(NAME_LENGHT); 
   if (s->name == NULL) {
       printf("Allocation Failed\n");
       return NULL;
   } else {
       printf("Allocation completed successfully\n");
   }
   //alternatively you can strdup directly without any allocation
   // s->name = strdup("some name");
   return s; 
}   

答案 2 :(得分:-3)

您永远不会更改s中的main

解决方案1:将main中的变量指针传递给init以填充。

void init_student(student** s_ptr) {
    *s_ptr = (student*)malloc(sizeof(student));
    if (*s_ptr == NULL) {
        fprintf(stderr "panic: Allocation Failed\n");
        exit(1);
    }

    (*s_ptr)->name = malloc(MAX_NAME_SIZE + 1);
    if ((*s_ptr)->name == NULL) {
        fprintf(stderr "panic: Allocation Failed\n");
        exit(1);
    }

    (*s_ptr)->name[0] = 0;

    (*s_ptr)->gpa = 0;
}   

void delete_student(student* s) {
    free(s->name);
    free(s);
}

int main() {
    student* s;
    init_student(&s);
    delete_student(s);
    return 0;
}

解决方案1b:相同,但更清洁。

void init_student(student** s_ptr) {
    student* s = (student*)malloc(sizeof(student));
    if (*s_ptr == NULL) {
        fprintf(stderr "panic: Allocation Failed\n");
        exit(1);
    }

    s->name = malloc(MAX_NAME_SIZE + 1);
    if (s->name == NULL) {
        fprintf(stderr "panic: Allocation Failed\n");
        exit(1);
    }

    s->name[0] = 0;

    s->gpa = 0;

    *s_ptr = s;
}   

void delete_student(student* s) {
    free(s->name);
    free(s);
}

int main() {
    student* s;
    init_student(&s);
    delete_student(s);
    return 0;
}

解决方案2:将分配的点返回main

student* init_student() {
    student* s = (student*)malloc(sizeof(student));
    if (s == NULL) {
        fprintf(stderr "panic: Allocation Failed\n");
        exit(1);
    }

    s->name = malloc(MAX_NAME_SIZE + 1);
    if (s->name == NULL) {
        fprintf(stderr "panic: Allocation Failed\n");
        exit(1);
    }

    s->name[0] = 0;

    s->gpa = 0;

    return s;
}   

void delete_student(student* s) {
    free(s->name);
    free(s);
}

int main() {
    student* s = init_student();
    delete_student(s);
    return 0;
}

请注意&s == NULL永远不会成立,因为&s是变量本身的地址。您只需要s == NULL检查s中指针的值。