堆上分配的C free char *

时间:2010-10-24 19:06:31

标签: c memory-leaks char free heap

以下代码示例中是否存在内存泄漏,因为我已在堆上为已释放的名称分配了内存?如果我添加免费(person->名称);在免费(人)之前;然后我在VS中得到一个运行时错误“CRT检测到应用程序在堆缓冲区结束后写入内存”。

header.h:

#ifndef HEADER
#define HEADER

typedef struct person {
 char *name;
} Person;

#endif

由source.c:

#include <stdio.h>
#include <stdlib.h>
#include "header.h"

#define BUFFERSIZE 500

int main (int argc, char* argv[]){
 Person *person = NULL;
 char buffer[BUFFERSIZE];
 printf("Enter name\n");
 fgets(buffer, BUFFERSIZE, stdin);
 {
  char *name; 
  person = malloc(sizeof(Person));
  name = malloc(strlen(buffer));
  strcpy (name,buffer);
  person->name = name;
 }
 free(person); 
 return 0;
}

谢谢,Rob

4 个答案:

答案 0 :(得分:10)

strlen不考虑strcpy添加的null终止符,你需要“malloc(strlen(buffer)+1)”

答案 1 :(得分:9)

是的,代码有内存泄漏。

罪魁祸首是: name = malloc(strlen(buffer));应该是 name = malloc(strlen(buffer)+1);代表\0

您现在应该可以免费person->name

答案 2 :(得分:3)

是。内存泄漏。

您分配名称缓冲区:

name = malloc(strlen(buffer));

永远不会解除分配。然后当您取消分配Person时,

free(person); 

你丢失了指向该缓冲区的最后一个指针,因此你永远不会解除分配它。

您收到的错误消息是与您分配的名称缓冲区长度相关的单独问题,不足以包含您尝试复制到其中的字符串的空终止。

答案 3 :(得分:1)

name永远不会被释放,所以它会泄漏。

像这样的复杂堆分配结构通常最好通过转移到C ++来处理,或者(如果这不可行)通过将内存管理包装在自定义创建/销毁/操作函数中来处理:

Person *CreatePerson(void) {
    /* you can use calloc() here, of course */
    Person *result = malloc(sizeof(Person));
    if (result) {
        memset(result, 0, sizeof(Person));
    }
    return result;
}

void DestroyPerson(Person *p) {
    if (p) {
        free(p->name);
        free(p);
    }
}

void SetPersonName(Person *p, const char *name) {
    if (p) {
        if (p->name) {
            free(p->name);
            p->name = NULL;
        }

        if (name) {
            size_t len = strlen(name);
            p->name = malloc(len + 1);
            if (p->name) {
                strncpy(p->name, name, len);
                p->name[len] = 0;
            }
        }
    }
}

const char *GetPersonName(const Person *p) {
    if (p)
        return p->name;
    return NULL;
}

但是,正如您所看到的代码量所示,C ++通常是更好的选择:

class Person {
    private: std::string name;

    public: const std::string& getName(void) const {
        return this->name;
    }

    public: void setName(const std::string& newName) {
        this->name = newName;
    }
};

更短,更清洁,更清晰!