欢聚时代(YY)面试

C++内存管理和对齐

欢聚时代在广州的总部还是有点偏的,但是好在有专车接送,就方便多了。费话不多说,直接上题,下面是个人当时回答得不完整或是没回答上来的问题!!!

问题1:#program pack(n)的作用

在搞清楚这个问题之前先看看在vs2013环境下占用的字节大小:

int main(){
	cout << "long float:"<<sizeof(long float) << endl;
	cout << "float:" << sizeof(float) << endl;
	cout << "long int:" << sizeof(long int) << endl;
	cout << "long long int:" << sizeof(long long int) << endl;
	cout << "double:" << sizeof(double) << endl;
	cout << "long double:" << sizeof(long double) << endl;
	cout << "long:" << sizeof(long) << endl;
	return 0;
}


字节对齐(默认方式):

#pragma pack()
struct s1{
	short a;
	long b;
};
struct s2{
	char c;
	s1 d;
	long long e;
};

struct s3{
	int a;
	int b;
	char c;
	double d;
};
int main(){
	cout << "s1: "<<sizeof(s1) << endl;
	cout << "s2: " <<sizeof(s2) << endl;
	cout << "s3: " << sizeof(s3) << endl;
	s3 node[2];
	for (int i = 0; i < 2;i++){
		printf("%p\n", &node[i].a);
		printf("%p\n", &node[i].b);
		printf("%p\n", &node[i].c);
		printf("%p\n", &node[i].d);
		cout << endl;
	}
	return 0;
}
输出:


在这种情况下,每个元素的开始地址都是按照自己的长度对齐,在s3结构体里面,元素a的偏移量为0,b的偏移量为4,c的偏移量为8,d不能从9开始,只能从16开始,占用

后续的8个字节,所以一共24字节!!!!!

修改:#pragma pack()->#pragma pack(4),输出结果如下:


一旦我们指定了字节对齐数,那么对齐量就是min{自身数据长度,n},很显然,s3中最后一个元素的对齐量不是8而是4,所以d不能从9开始,但是可以从12开始(可以整除4),所以s3占用的字节数是20字节!!!!


问题2:如何解决内存泄露

在博客上找到一篇相关文章http://blog.youkuaiyun.com/kangroger/article/details/39317503,其中有个办法是内存泄露的关键就是记录分配的内存和释放内存的操作,看看能不能匹

配。跟踪每一块内存的声明周期,例如:每当申请一块内存后,把指向它的指针加入到List中,当释放时,再把对应的指针从List中删除,到程序最后检查List就可以知道有没有

内存泄露了。Window平台下的Visual Studio调试器和C运行时(CRT)就是用这个原理来检测内存泄露。

根据以上的思想我重载了全局new操作符和delete操作符,一旦有分配内存的操作,我们就将其保存在link的队列中,一旦有释放内存的操作,就将其中链表中删除;如果申请

空间和释放空间的操作时匹配的那么,最终队列为空,这样我们就可以模仿检测内存泄露!!!!

下面是源码:

#include<iostream>
#include<vector>
#include<list>
#include<fstream>
#include<string>
#include<set>
#include<map>
#include<algorithm>
#include<stack>
#include <typeinfo> 
#include<bitset>
#include<cstdio>
#include <stdarg.h> 
#include<functional>
using namespace std;


class base{
public:
	int a;
	int b;
	base(){
		a = 1;
		b = 2;
	}
};

typedef struct mem{
	void *ptr;
	struct mem *next;
	mem() :ptr(NULL){};
}node, *link;

static link head = NULL;

void* operator new(size_t n){
	cout << "this is a overload new!"<< endl;
	void *p = malloc(n);
	if (!p)cout << "out of memory!"<< endl;
	link temp = (link)malloc(sizeof(mem));
	temp->ptr = p;
	temp->next = NULL;
	if (head == NULL)head = temp;
	else {//将其插入到head指针中,采用头插法
		temp->next =head;
		head = temp;
	}
	return p;
}

void operator delete(void *p){
	cout << "this is a overload delete!" << endl;
	if (head != NULL){
		link temp;
		if (head->ptr == p){//和链表的头结点相等
			temp = head;
			head = head->next;
			free(temp->ptr);
			free(temp);
			return;
		}
		link now = head;
		while (now->next != NULL&&now->next->ptr != p)now = now->next;
		//处理相关结点
		temp = now->next;//找到匹配的
		now->next = now->next->next;
		free(temp->ptr);
		free(temp);
		return;
	}
}

int main(){
	base *ptr = new base;
	base *ptr1 = new base;
	delete ptr1;
	delete ptr;
	/*
	这里是你的代码......
	*/
	//记得head一定是放在程序的最后位置
	if (head != NULL)cout << "memory leak!"<< endl;
	return 0;
}

测试

我们只释放ptr或者ptr1其中的一个:

<pre name="code" class="cpp">int main(){
	base *ptr = new base;
	base *ptr1 = new base;
	delete ptr1;
	//delete ptr;
	/*
	这里是你的代码......
	*/
	//记得head一定是放在程序的最后位置
	if (head != NULL)cout << "memory leak!"<< endl;
	cout << "the leaked memory start at:0x"<<head->ptr<< endl;
	return 0;
}

 测试结果: 


综上所述,面试的过程中会被经常问到的关于内问题有内存溢出,内存泄露,悬垂指针(野指针,设置一个智能指针类,添加一个计数器,详情参见我的博客:点击打开链接)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值