C++中的内存管理

C/C++内存布局

http://www.cnblogs.com/clover-toeic/p/3754433.html

名称

存储内容

局部变量、函数参数、返回地址等

动态分配的内存

BSS

未初始化或初值为0的全局变量和静态局部变量

数据段

已初始化且初值非0的全局变量和静态局部变量

代码段

可执行代码、字符串字面值、只读变量

every process stores data starting at 0x08048000 in 32 bit machine (and 0x00400000 in 64 bit machine).

 

基本内存分配方式

  1. 程序中的全局变量,静态变量等是从静态储存去分配。
  2. 局部变量,函数参数等是分配在栈上,有编译器负责,处理器一般内置栈内存分配指令,效率高。
  3. 动态分配的内存放在堆上,由程序员控制。

 

动态内存分配

C语言中通过 malloc()  free() 来分配内存。

C++中新增new  delete操作符

 

mallocfree

  1. void* malloc (size_t size);
  2. void* calloc (size_t num, size_t size);

Allocates a block of memory for an array of num elements, each of them size bytes long, and initializes all its bits to zero.

  1. void* realloc (void* ptr, size_t size);

Reallocate memory block

Changes the size of the memory block pointed to by ptr.

如果大于ptr指向的原有内存大小,会从新分配内存,原有ptrfree

  1. void free (void* ptr);

Deallocate memory block

 

一般能使用栈存储和静态存储就不使用堆。原因是:

  1. 堆上分配内存需要调用操作系统的内存管理模块的堆管理器,搜索其中是否有符合要求的空闲的连续字节内存块。如果没有还需要碎片合并。

会带来额外的开销。

  1. 需要检查是否分配成功,以及需要显试的free

 

注意点:

  1. free后,指针仍然存在,只是指向的内容变为了垃圾。
  2. 这个时候,这个指针就叫野指针

 

new  delete

三种new

  1. 普通的new,如果分配失败,会抛出bad_alloc异常
  2. nothrow new,如果分配失败,返回null指针
  3. placement new,在已经分配的内存中重新调用对象的构造函数

还可以直接调用全局函数 ::operator new()

这个时候分配内存,但是不会构造函数。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

// operator new example
#include <iostream>     // std::cout
#include <new>          // ::operator new

struct MyClass {
  int data[100];
  MyClass() {std::cout << "constructed [" << this << "]\n";}
};

int main () {

std::cout << "1: ";
  MyClass * p1 = new MyClass;
      // allocates memory by calling: operator new (sizeof(MyClass))
      // and then constructs an object at the newly allocated space

std::cout << "2: ";
  MyClass * p2 = new (std::nothrow) MyClass;
      // allocates memory by calling: operator new (sizeof(MyClass),std::nothrow)
      // and then constructs an object at the newly allocated space

std::cout << "3: ";
  new (p2) MyClass;
      // does not allocate memory -- calls: operator new (sizeof(MyClass),p2)
      // but constructs an object at p2

// Notice though that calling this function directly does not construct an object:
  std::cout << "4: ";
  MyClass * p3 = (MyClass*) ::operator new (sizeof(MyClass));
      // allocates memory by calling: operator new (sizeof(MyClass))
      // but does not call MyClass's constructor

delete p1;
  delete p2;
  delete p3;

return 0;
}

 

来自 <http://www.cplusplus.com/reference/new/operator%20new/>

 

注意使用placement new的析构问题。

 

placement new 用处

  1. 可以管理一片分配的内存,避免反复的释放获取
  2. placement new还可以解决的一个问题是建立带参数的构造函数对象数组。

代码示例如下:

 1 class CPong

 2 {

 3 public:

 4     CPong( int m ) : v(m) { std::cout << "CPong ctor." << std::endl; }

 5 

 6 private:

 7     int v;

 8 };

 9 char* pong = new charsizeof(CPong) * 10 ];

10 CPong* pp = (CPong*)pong;

11 

12 for ( int i=0; i<10; ++i )

13 {

14     new (pp+i)CPong(i);

15 }

16 

17 for ( int j=0; j<10; ++j )

18 {

19     pp[j].~CPong();

20 }

21 

22 delete [] pong;

 

来自 <http://www.cppblog.com/kongque/archive/2010/02/20/108093.html>

 

使用placement new怎么解决析构以及释放内存

Using the new operator does two things, it calls the function operator new which allocates memory, and then it uses placement new, to create the object in that memory. The delete operator calls the object's destructor, and then calls operator delete. Yeah, the names are confusing.

//normal version                   calls these two functions
MyClass* pMemory = new MyClass;    void* pMemory = operator new(sizeof(MyClass));
                                   
MyClass* pMyClass = new( pMemory ) MyClass();
//normal version                   calls these two functions
delete pMemory;                    pMyClass->~MyClass();
                                   
operator delete(pMemory);

Since in your case, you used placement new manually, you also need to call the destructor manually. Since you allocated the memory manually, you need to release it manually. Remember, if you allocate with new, there must be a coressponding delete. Always.

 

来自 <http://stackoverflow.com/questions/8918791/how-to-properly-free-the-memory-allocated-by-placement-new>

 

也就是本来的new 对应两个操作

  1. 分配内存,operator new();
  2. 调用构造函数,placement new

本来的delete调用两个操作:

  1. 调用析构函数
  2. 调用operator delete

现在我们既然直接调用构造函数,那么也需要直接的调用析构函数,而且不能调用delete表达式,需要调用operator delete 。例子

 

What is the right method to delete all the memory allocated here?

  const char* charString = "Hello, World";
  
void *mem = ::operator new(sizeof(Buffer) + strlen(charString) + 1);
  
Buffer* buf = new(mem) Buffer(strlen(charString));

delete (char*)buf;

OR

  const char* charString = "Hello, World";
  
void *mem = ::operator new(sizeof(Buffer) + strlen(charString) + 1);
  
Buffer* buf = new(mem) Buffer(strlen(charString));

delete buf;

or are they both same?

 

The correct method is:

buf->~Buffer();
::
operator delete(mem);

You can only delete with the delete operator what you received from the new operator. If you directly call the operator new function, you must also directly call the operator delete function, and must manually call the destructor as well.

 

来自 <http://stackoverflow.com/questions/6783993/placement-new-and-delete>

 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10

 A *pa1 = new A;

//  pa1->~A();
    //  delete pa1;

B *pb1 = new (pa1) B(5);

pb1->~B();
    ::operator delete(pb1);
    // delete pa1;

如果直接调用delete就会重复调用析构函数,这里需要调用 operator delete

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值