malloc/free 和 new/delete

Author Avatar
Aryb1n 8月 25, 2017

malloc和new应当是都在堆上分配内存, 但有一点区别

mallloc & free

从malloc工作原理来看, 就仅仅是分配一块大小合适的地方…以前笔记也有记录过, 最初是从顶块上割下来一块用, free掉后会进入fast bin, 或者其他的bin链表里, 再后来malloc的话, 根据大小, 从不同的bin上取下来, 返回的是User Data的起始地址, 不包括chunk header, 很纯粹, 只是分配空间给你, 没有初始化还是其他什么的内容

从语言层面来看, malloc返回的是void *的类型, 所以在使用的时候要强制类型转换一下

对了, 实际使用过程中, malloc之后应当检测一下, 结果是不是NULL, 然后再使用(我下面没写)

free的话就是…emmmmm, 把分出去的chunk给收回来, 放到空闲链表里…其实就是增加了fd, bk, 指针

我写了一个蹩脚的链表. 然后怀疑人生中

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct node {
    struct node * next;
    int val;
}Node;
int main() {
    Node * list = (Node *)malloc(sizeof(Node));
    list -> val = 111;
    list -> next = (Node *)malloc(sizeof(Node));
    list -> next -> val = 222;
    list -> next -> next = NULL;
    Node * ptr = list;
    while(ptr != NULL) {
        printf("%d\n", ptr -> val);
        ptr = ptr -> next;
    }
    printf("print done\n");
    ptr = list;
    while(ptr != NULL) {
        Node * temptr = ptr;
        ptr = ptr -> next;
        free(temptr);
    }
    printf("free done\n");
    return 0;
}

new & delete

这个其实我不太熟悉, 因为我不太会oop, 所以很少用
只知道new是C++的一个操作符…

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
class A {
    private:
        static int num;
    public:
        int a;
        A() {num++; puts("num++");}
        A(int _a):a(_a * _a) {num++; puts("num++");}
        void b() {printf("[*]%d a: %d", num, a);}
};
int A::num = 0;
int main() {
    A * a1 = new A;
    a1 -> b();
    puts("");

    A * a2 = new A();
    a2 -> b();
    puts("");

    A a3;
    a3.b();
    puts("");

    A * a4 = (A * )malloc(sizeof(A));
    a4 -> b();
    return 0;
}
/*
num++
[*]1 a: 0

num++
[*]2 a: 0

num++
[*]3 a: 2

[*]3 a: 0
*/

首先有个重要的问题就是, 类内的静态成员变量要在类外进行定义…不然就会出现未定义的引用..就像我这里写的那个int A::num = 0
类内部写的静态成员, 相当于是只做了一个申明, 只是有了一个scope, 但要使用(存储)的话必须要在类外定义一下

静态其实是讲与程序有着相同的生命周期…所以静态变量即便是局部的…也只是作用域在局部…但却是一直存在的, 所以也只会经历一次初始化, 从存储上讲的话, 静态变量和全局变量是一样的…未初始化的在bss, 初始化的在data

跑题了….从上面就可以看出来的new和malloc的区别

  1. malloc返回的指针是void *的, 需要强制转化, 而new的话返回的就不需要了
  2. malloc分配的大小需要自己定, new的话不需要
  3. malloc不会调用构造函数…这个从最后一个没有num++可以看出来,当然简单数据类型的话new也不调用
  4. new分配失败好像会触发异常, 所以不能通过是否返回NULL来判断分配成功与否

所以相应的delete不光是会回收空间, 可能还会调用析构函数

据说是new分三个过程

  1. 调用operator new(size), 比如 new int, 差不多汇编是这样子
    push 4
    call operator new(size)
    add esp, 4
    
  2. 在分配的内存空间上, 调用构造函数(基本类型没有在这个操作)
  3. 转换指针类型??? (这个我也不太确定)

这里看到上面四个生成类的方法, 还想讲几点

有括号和没括号的区别

  1. 对于内置类型, 比如int
    new int // 不会初始化
    new int() //会初始化为0
    
  2. 对于类
  • 没括号是默认初始化
  • 有括号是值初始化

结论: 我还是加括号吧, 这个我还是不太清楚

用new和不用new的区别

new底下调用的是malloc, 是在堆上分配内存
不new的话…就是在栈上了呗…

另外, 不new的话, 也有隐和显两种写法

A a = A(2);
A a(2);

差不多就这样子了