发布网友
共2个回答
热心网友
无效指针操作。应该是程序中处理内存操作出错。可能是由于程序本身的bug (大几率) 或者由于机器本身内存不兼容导致 (小几率)。
热心网友
嵌入式Linux开发《C语言专题(五:(3)实用的内存函数6)》
嵌入式软硬件开发
2019-02-12 · 优质教育领域创作者
在文章嵌入式Linux开发《C语言专题(五:(3)实用的内存函数4)》嵌入式Linux开发《C语言专题(五:(3)实用的内存函数5)》中对C语言中内存操作函数做了部分介绍。最后留了与malloc&free有关的几个问题,这篇文章将用代码和结果来分析这些问题,如下所示:
1)malloc(0)真的是申请0空间吗?malloc(100)呢?
2)malloc 多次free 1次 或者malloc 1次 free多次?
3)没有检查内存分配是否成功?
4)使用申请的动态内存时超出了申请的内存边界?
5)释放一部分内存空间?
6)试图访问已经释放的内存?
(1)malloc(0)真的是申请0空间吗?malloc(100)呢?
代码演示:
#include <stdio.h>
//一定要加上操作头文件
#include <stdlib.h>
#define NUMBER 4
//演示malloc(0)和malloc(100)
int main(int argc, char** argv)
{
int i = 0;
int *p = NULL;
//第一步:申请内存空间
p = (int *)malloc(0);
//p = (int *)malloc(100);
//第二步:检查返回值
if(NULL == p)
{
printf("申请内存空间出错");
//如果出错,退出整个进程
exit(-1);
}
printf("申请的地址为 = %p \n", p);
//第三步:暂时先不使用内存空间
//第四步:释放内存空间
free(p);
p = NULL;
return 0;
}
运行结果:
lz@ubuntu:~/share$ ./memory
申请的地址为 = 0x98ab008
lz@ubuntu:~/share$ ./memory
申请的地址为 = 0x86c5008
lz@ubuntu:~/share$ ./memory
申请的地址为 = 0x8534008
分析结果:malloc(0)和malloc(100)返回的结果不为NULL,malloc(0)的结果是一个合法的地址,并且每次返回的地址值不一样。
那么是否malloc(0)的地址可以使用?
代码演示:
#include <stdio.h>
//一定要加上操作头文件
#include <stdlib.h>
//当NUMBER的值小于等于3时,不会出错,否认就会出错,验证malloc(0)返回未必是空地址
#define NUMBER 4
//演示malloc(0)
int main(int argc, char** argv)
{
int i = 0;
int *p = NULL;
//第一步:申请内存空间
p = (int *)malloc(0);
//第二步:检查返回值
if(NULL == p)
{
printf("申请内存空间出错");
//如果出错,退出整个进程
exit(-1);
}
printf("申请的地址为 = %p \n", p);
//第三步:使用内存空间
for(i=0; i<NUMBER; i++)
{
//将所申请的内存空间赋值为0
p[i] = 0;
printf("p[%d] = %d \n", i, p[i]);
}
//第四步:释放内存空间
free(p);
p = NULL;
return 0;
}
运行结果:
lz@ubuntu:~/share$ ./memory
申请的地址为 = 0x857b008
p[0] = 0
p[1] = 0
p[2] = 0
p[3] = 0
*** Error in `./memory': free(): invalid next size (fast): 0x0857b008 ***
Aborted (core mped)
分析结果:当NUMBER大于等于4时,在 free()时出现段错误,小于4时,正确。因此,在实际的研发时不要使用malloc(0),这个没有意义。 官方解释是当malloc(0)也可能返回NULL或者是一个独特的指针,这个指针随后传递给free。
(int *)malloc(100)一定是申请25个整型数据个数吗?
答:p=(int *)malloc(100)申请的整型数据个数并不能确定是25个,因为在不同的系统中int所占的字节数不同。如果是在32位操作系统中,那么就是,如果是在位操作系统中就不是了。如果想要申请存储25个整型数据,为了可移植性,可使用p=(int*)malloc(sizeof(int)*25)。注意sizeof的使用方法。
(2)malloc 多次free 1次 或者malloc 1次 free多次?
代码演示:
#include <stdio.h>
//一定要加上操作头文件
#include <stdlib.h>
#define NUMBER 4
//演示malloc一次,free多次
int main(int argc, char** argv)
{
int i = 0;
int *p = NULL;
//第一步:申请内存空间
p = (int *)malloc(sizeof(int) * NUMBER);
//第二步:检查返回值
if(NULL == p)
{
printf("申请内存空间出错");
//如果出错,退出整个进程
exit(-1);
}
printf("申请的地址为 = %p \n", p);
//第三步:使用内存空间
for(i=0; i<NUMBER; i++)
{
//将所申请的内存空间赋值为0
p[i] = 0;
printf("p[%d] = %d \n", i, p[i]);
}
//第四步:释放内存空间
free(p);
free(p);//第二次free出错
p = NULL;
return 0;
}
运行结果:
lz@ubuntu:~/share$ ./memory
申请的地址为 = 0x9d2c008
p[0] = 0
p[1] = 0
p[2] = 0
p[3] = 0
*** Error in `./memory': double free or corruption (fasttop): 0x09d2c008 ***
Aborted (core mped)
分析结果:错误显示是2次free导致的段错误。因为第一次已经将返回的地址及申请的内存空间释放了,此时p就是异常内存地址,再次释放当然会出错。因此,在实际操作时申请一次释放一次就可以。
只malloc不free会怎样?
代码演示:
#include <stdio.h>
//一定要加上操作头文件
#include <stdlib.h>
#define NUMBER 100000000
//演示申请内存空间,但是不free
int main(int argc, char** argv)
{
int *p = NULL;
//申请内存空间
while(1)
{
p = (int *)malloc(sizeof(int) * NUMBER);
}
return 0;
}
如果申请的内存空间没有得到有效释放,那么总有一天堆会被撑爆(因为堆空间大小是一定的),导致系统终止运行。这种现象称之为内存泄漏即动态申请内存之后,当不再使用时没有释放这些内存,导致系统的内存被一点一点的消耗 最终导致系统崩溃,之后只能通过重启系统解决。所以也就告诫我们当不使用内存时,一定要记得释放内存,以便于后续重新被分配使用。
(3)没有检查内存分配是否成功?
答:在使用malloc时一定要检查返回值是否为NULL,如果返回值为NULL,而没有检查,会导致直接使用返回值为NULL的地址空间,导致出现Segmentation fault (core mped)段错误,因为我们访问了异常空间。
(4)使用申请的动态内存时超出了申请的内存边界?
代码演示:
#include <stdio.h>
//一定要加上操作头文件
#include <stdlib.h>
//需要10个整数但实际只申请4个
#define NUMBER 10
//演示使用申请的动态内存时超出了申请的内存边界
int main(int argc, char** argv)
{
int i = 0;
int *p = NULL;
//第一步:申请内存空间
p = (int *)malloc(sizeof(int)*4);
//第二步:检查返回值
if(NULL == p)
{
printf("申请内存空间出错");
//如果出错,退出整个进程
exit(-1);
}
printf("申请的地址为 = %p \n", p);
//第三步:使用内存空间
for(i=0; i<NUMBER; i++)
{
//将所申请的内存空间赋值为0
p[i] = 0;
printf("p[%d] = %d \n", i, p[i]);
}
//第四步:释放内存空间
free(p);
p = NULL;
return 0;
}
运行结果:
lz@ubuntu:~/share$ ./memory
申请的地址为 = 0x90bf008
p[0] = 0
p[1] = 0
p[2] = 0
p[3] = 0
p[4] = 0
p[5] = 0
p[6] = 0
p[7] = 0
p[8] = 0
p[9] = 0
*** Error in `./memory': free(): invalid next size (fast): 0x090bf008 ***
Aborted (core mped)
分析结果:段错误 虽然申请4个空间但是可以访问10个空间,虽然有时候可以访问超过申请的内存空间,但是这样做可能无意间冲掉原来的内存空间的值,所以最好不要这样做。
(5)释放一部分内存空间?
代码演示:
#include <stdio.h>
//一定要加上操作头文件
#include <stdlib.h>
#define NUMBER 4
//演示释放一部分内存空间
int main(int argc, char** argv)
{
int i = 0;
int *p = NULL;
//第一步:申请内存空间
p = (int *)malloc(sizeof(int) * NUMBER);
//第二步:检查返回值
if(NULL == p)
{
printf("申请内存空间出错");
//如果出错,退出整个进程
exit(-1);
}
printf("申请的地址为 = %p \n", p);
//第三步:使用内存空间
for(i=0; i<NUMBER; i++)
{
//将所申请的内存空间赋值为0
p[i] = 0;
printf("p[%d] = %d \n", i, p[i]);
}
//第四步:释放内存空间
free(p+1);//释放一部分内存空间 出错
p = NULL;
return 0;
}
运行结果:
lz@ubuntu:~/share$ ./memory
申请的地址为 = 0x9112008
p[0] = 0
p[1] = 0
p[2] = 0
p[3] = 0
*** Error in `./memory': free(): invalid pointer: 0x0911200c ***
Aborted (core mped)
分析结果:段错误,申请的起始地址p是 0x9112008 p+1的地址是0x0911200c不是申请的起始地址,所以出错。
(6)试图访问已经释放的内存?
#include <stdio.h>
//一定要加上操作头文件
#include <stdlib.h>
#define NUMBER 4
//演示试图访问已经释放的内存
int main(int argc, char** argv)
{
int i = 0;
int *p = NULL;
//第一步:申请内存空间
p = (int *)malloc(sizeof(int) * NUMBER);
//第二步:检查返回值
if(NULL == p)
{
printf("申请内存空间出错");
//如果出错,退出整个进程
exit(-1);
}
//第三步:使用内存空间
for(i=0; i<NUMBER; i++)
{
//将所申请的内存空间赋值为2
p[i] = 2;
printf("p[%d] = %d \n", i, p[i]);
}
//第四步:释放内存空间
free(p);
p[3] = 1;//试图访问已经释放的内存
printf("p[3] = %d \n", p[i]); //为0 既不是1也不是2
p = NULL; //放在p[3] = 1;后面不会出现段错误,放在前面会出现
return 0;
}
运行结果:
lz@ubuntu:~/share$ ./memory
申请的地址为 = 0x9c33008
p[0] = 2
p[1] = 2
p[2] = 2
p[3] = 2
p[3] = 0
分析结果:没有达到使得p[3] = 1,因为原来申请的地址空间已经被释放了。也不是原来的值2,而是0,表示此时访问原来地址的内容已经无效了。所以我们不要访问已经释放申请的内存空间的值。
总结:把这些问题通过敲代码分析结果搞明白,就可以搞定与malloc&free有关的问题。
未完待续,后续继续更新内存函数具体用法...
更多精彩内容可以关注此头条号:嵌入式软硬件开发 喜欢的话大家可以“评论”,“转发”、“点赞”或者“收藏”,感谢大家。相互交流,共同成长。
搜索
初学编程100个代码
十大编程代码大全
c语言编程新手入门教程
嵌入式编程入门教学
自己学c语言有前途吗
c语言知识点总结归纳