在为结构体分配内存时,运行时系统不会自动为结构体内部的指针分配内存。类似地,当结构体消失时,运行时系统也不会自动释放结构体内部的指针指向的内存。
考虑如下结构体:
typedef struct _person {
    char* firstName;
    char* lastName;
    char* title;
    uint age;
} Person;
当我们声明这个类型的变量或者为这个类型动态分配内存时,三个指针会包含垃圾数据。在下面的代码片段中,我们声明了Person,其内存分配如下图所示,三个点表示未初始化的内存。
void processPerson() {
    Person 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;
}
可以如下这样使用这个函数,下图说明了内存分配情况:
void processPerson() {
    Person person;
    initializePerson(&person, "Peter", "Underwood", "Manager", 36);
    ...
}
int main() {
    processPerson();
    ...
}

因为这个声明是函数的一部分,函数返回后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);
}
另外,我们必需记得调用initialize和deallocate函数,但诸如C++这类面向对象的编程语言会自动为对象调用这些操作。
如果用Person指针,必须释放如下所示的person:
void processPerson() {
    Person *ptrPerson;
    ptrPerson = (Person*) malloc(sizeof(Person));
    initializePerson(ptrPerson, "Peter", "Underwood", "Manager", 36);
        ...
    deallocatePerson(ptrPerson);
    free(ptrPerson);
}
下图说明了内存分配情况。

极客教程