Linux C 内存管理-实例分析

15 篇文章 1 订阅

Linux C 内存管理-实例分析

  Linux C 内存管理其实可以总结成一句话:管理你该管理的。即由系统静态分配的内存不要去释放,系统会在变量生命期结束时自动释放内存,而自己动态分配的内存则需要主动释放,同时要注意,同一块内存不要释放两次,更多具体关于Linux 内存管理的介绍可参考Linux内存管理以及段错误(核心已转储)。接下来通过一个实例来讲述下内存管理的过程。
  给定了一个字符串指针,并为其分配了一定的地址空间,如下所示:

#include<stdlib.h>
#include<stdio.h>
#include<string.h>

int main (){
	char* testData = (char*)malloc(5120);		
	//....
	if(testData != NULL){
		free(tesData);	
		testData = NULL;
	}	
	return 0;
}

接下来需要针对此字符串指针(地址)完成一些操作:
一、为其赋值并拷贝至其它字符串中:
  我们一般可能会这样做:

#include<stdlib.h>
#include<stdio.h>
#include<string.h>

int main (){
	char* testData = (char*)malloc(5120);		
	memcpy(testData, "Hello World", sizeof("Hello World"));    //这里注意,虽然字符串长度为11,但实际上向testData拷贝了12个字节的数据,其中最后一个数据为'\0'终止符,在进行字符串拷贝时需要注意。
	char *tarData = (char*)malloc(1024);
	tarData = testData;
	printf("%s\n", tarData);
	if(tarData  != NULL){
		free(tarData);
		tarData = NULL;
	}
	if(testData != NULL){
		free(tesData);	
		testData = NULL;
	}	
	return 0;
}
//double free or corruption (out): 

  以上代码虽然通过了编译,但是运行时会发现提示double free or corruption (out),这种提示便是我们对同一块地址空间释放了两次或者数据越界,但上面那种情况便是前者了。接下来分析下为什么会这样,在定义tarData时,我们为其动态分配了一块空间,而后将tarData指针指向了testData的地址,没错,此时tarData所指向的空间已不再是我们为其分配的空间了,如此一来,不管有没有输出成功,在我们想释放为tarData分配的空间时,即free(tarData)(注意这里主动将tarData=NULL;的目的是防止通过tarData指针操作了不该操作的空间)后,其实释放的是一开始为testData所分配的空间,这样一来,后面free(tesData); 再次对testData指向的空间进行释放,自然就报了上面的错误,当然还有小伙伴在为tarData分配了空间后,并未对其进行释放,这样虽然不会报错,但是只申请空间却不释放,不是个好习惯,甚至还会报出头疼的段错误。正确做法应该是,命名一个字符串指针直接指向testData所指向的地址,即:

#include<stdlib.h>
#include<stdio.h>
#include<string.h>

int main (){
	char* testData = (char*)malloc(5120);		
	memcpy(testData, "Hello World", sizeof("Hello World"));    //这里注意,虽然字符串长度为11,但实际上向testData拷贝了12个字节的数据,其中最后一个数据为'\0'终止符,在进行字符串拷贝时需要注意。
	char *tarData = testData ;
	printf("%s\n", tarData);
	if(testData != NULL){
		free(tesData);	
		testData = NULL;
	}	
	return 0;
}
//out:Hello World

二、将其截取分析后并拷贝至其它字符串中或对其进行其它操作
  比如一开始我是这么写的:

#include<stdlib.h>
#include<stdio.h>
#include<string.h>

void encode(char *buf)
{
	char *header = (char*)malloc(1024);
	header = buf;
	if (header[0] & 0x80 == 0)
	{
		//....
	}
	if(header != NULL)
	{
		free(header);
		header = NULL;
	}
}

int main (){
	char* testData = (char*)malloc(5120);		
	memcpy(testData, "Hello World", sizeof("Hello World"));    //这里注意,虽然字符串长度为11,但实际上向testData拷贝了12个字节的数据,其中最后一个数据为'\0'终止符,在进行字符串拷贝时需要注意。
	encode(testData);
	char *tarData = testData ;
	printf("%s\n", tarData);
	if(testData != NULL){
		free(tesData);	
		testData = NULL;
	}	
	return 0;
}
//segmentation fault

  于是我很正常的领到了“段错误”的error,其实和示例一一样,在encode()函数中,随手写的释放空间,其实释放的是为testData分配的空间(指针作为函数参数入参时,传的是地址),这样在经过encode()函数后,testData指向的空间已被释放,此时testData所指向的内存地址便不存在了,再将tarData指向至此时,就产生了试图访问一个不存在的内存地址的问题,于是很自然的报了段错误,正确做法应该是像示例一一样定义后直接指向testData所指向的地址,或者将testData指向地址内的值拷贝至header中,而后再单独对header进行释放,即:

#include<stdlib.h>
#include<stdio.h>
#include<string.h>

void encode(char *buf)
{
	
	char *header = (char*)malloc(1024);
	memcpy(header, buf, 1024);
	
	//char *header = buf;		//示例一的做法
	if (header[0] & 0x80 == 0)
	{
		//....
	}
	if(header != NULL)			//将值拷贝到单独分配的地址中,之后便可正常释放空间	
	{
		free(header);
		header = NULL;
	}
}

int main (){
	char* testData = (char*)malloc(5120);		
	memcpy(testData, "Hello World", sizeof("Hello World"));    //这里注意,虽然字符串长度为11,但实际上向testData拷贝了12个字节的数据,其中最后一个数据为'\0'终止符,在进行字符串拷贝时需要注意。
	encode(testData);
	char *tarData = testData ;
	printf("%s\n", tarData);
	if(testData != NULL){
		free(tesData);	
		testData = NULL;
	}	
	return 0;
}
//out:Hello World
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值