以下代码示例中是否存在内存泄漏,因为我已在堆上为已释放的名称分配了内存?如果我添加免费(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
答案 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;
}
};
更短,更清洁,更清晰!