问题描述
#include <stdio.h>
#include <stdio.h>
const int STRSIZR = 10;
int main()
{
char *str = (char *)malloc(STRSIZR*sizeof(char));
str = "string";
printf("%s\n", str);
free(str);
}
乍一看,这块代码没有什么问题。直接书写时vscode也没有进行报错,可运行后便会弹出错误:
free(): invalid pointer
问题原因
开启断点调试
在第一次分配空间之后,str指针指向分配好的地址 0x5555555592a0
再执行一步,
此时str指针指向了地址 0x555555556008,此处为字符串"string"的存放地址,即text 区域(也称为代码段)
造成两个问题
- 释放代码段区域的空间必然导致错误(错误诱发原因)
- 原有分配的内存空间丢失
或许这也是使用g++编译时提示ISO禁止将string转化为char*的原因之一
问题解决
#include <stdio.h>
#include <stdio.h>
#include <string.h>
const int STRSIZR = 10;
int main()
{
char *str = (char *)malloc(STRSIZR*sizeof(char));
memset(str,0,STRSIZR*sizeof(char));
strcat(str,"string");
printf("%s\n", str);
free(str);
}
拓展-结构体中的char*
#include <stdio.h>
#include <stdio.h>
#include <string.h>
const int STRSIZR = 10;
typedef struct node
{
int index;
char *name;
} Node;
int main()
{
char *str = (char *)malloc(STRSIZR*sizeof(char));
memset(str,0,STRSIZR*sizeof(char));
Node *n = (Node *)malloc(sizeof(Node));
memset(n, 0, sizeof(Node));
n->name=str;
printf("%s\n", n->name);
free(n);
}
考虑以上代码,运行后不报错。可真的没有问题吗?
未必,仍然考虑内存管理。使用valgrind帮我们一探究竟
valgrind --leak-check=full ./program
是的,当我们释放Node的时候,其实只是释放了char* name这个指针(8个字节)的这块空间。而并不会将其对应的分配内存空间释放。
#include <stdio.h>
#include <stdio.h>
#include <string.h>
const int STRSIZR = 10;
typedef struct node
{
int index;
char *name;
} Node;
int main()
{
char *str = (char *)malloc(STRSIZR*sizeof(char));
memset(str,0,STRSIZR*sizeof(char));
Node *n = (Node *)malloc(sizeof(Node));
memset(n, 0, sizeof(Node));
n->name=str;
printf("%s\n", n->name);
free(n->name);
free(n);
}
先释放内部的char*,再释放整个结构体!