C结构体释放

在为结构体分配内存时,运行时系统不会自动为结构体内部的指针分配内存。类似地,当结构体消失时,运行时系统也不会自动释放结构体内部的指针指向的内存。

考虑如下结构体:

typedef struct _person {
    char* firstName;
    char* lastName;
    char* title;
    uint age;
} Person;

当我们声明这个类型的变量或者为这个类型动态分配内存时,三个指针会包含垃圾数据。在下面的代码片段中,我们声明了Person,其内存分配如图6-2所示,三个点表示未初始化的内存。

void processPerson() {
    Person person;
    ...
}

图6-2:未初始化的Person结构体

在这个结构体的初始化阶段,会为每个字段赋一个值。对于指针字段,我们会从堆上分配内存并把地址赋给每个指针:

void initializePerson(Person *person, const char* fn,
        const char* ln, const char* title, uint age) {
    person->firstName = (char*) malloc(strlen(fn) + 1);
    strcpy(person->firstName, fn);
    person->lastName = (char*) malloc(strlen(ln) + 1);
    strcpy(person->lastName, ln);
    person->title = (char*) malloc(strlen(title) + 1);
    strcpy(person->title, title);
    person->age = age;
}

可以如下这样使用这个函数,图6-3说明了内存分配情况:

void processPerson() {
    Person person;
    initializePerson(&person, "Peter", "Underwood", "Manager", 36);
    ...
}
int main() {
    processPerson();
    ...
}

图6-3:初始化的Person结构体

因为这个声明是函数的一部分,函数返回后person的内存会消失。不过,动态分配的内存不会被释放,仍然保存在堆上。不幸的是,我们丢失了它们的地址,因此无法将其释放,从而导致了内存泄漏。

用完这个实例后需要释放内存。下面的函数会释放之前创建实例时分配的内存:

void deallocatePerson(Person *person) {
    free(person->firstName);
    free(person->lastName);
    free(person->title);
}

我们需要在函数结束前调用这个函数:

void processPerson() {
    Person person;
    initializePerson(&person, "Peter", "Underwood", "Manager", 36);
    ...
    deallocatePerson(&person);
}

另外,我们必需记得调用initializedeallocate函数,但诸如C++这类面向对象的编程语言会自动为对象调用这些操作。

如果用Person指针,必须释放如下所示的person

void processPerson() {
    Person *ptrPerson;
    ptrPerson = (Person*) malloc(sizeof(Person));
    initializePerson(ptrPerson, "Peter", "Underwood", "Manager", 36);
        ...
    deallocatePerson(ptrPerson);
    free(ptrPerson);
}

图6-4说明了内存分配情况。

图6-4:指向person实例的指针

赞(1)

评论 抢沙发

评论前必须登录!

 

C指针