上次分享整理的面试知识点 I , 今天咱们来继续分享面试知识点整理 IIlinux
linux kernel 内核空间、内存管理、进程管理设备、驱动虚拟文件系统(vfs) | 内核空间是受保护的,用户不能对内核空间读写,不然会出现段错误 |
---|---|
环境变量(env) | PATH |
命令行参数 | char *agrv[] |
栈区⬇️ | 函数的返回地址,返回值,参数,局部变量 |
共享库(映射区)⬇️ | 调用动态库,或者mmap函数进行文件映射 |
堆区⬆️ | 用new/malloc申请的内存,同时须要适用delete/free来释放采用链式储存结构 |
.bss区 | 未初始化的全局变量和静态变量以及 初始化为 0 的 全局变量和静态变量编译时就已经分配了空间 |
.data区 | 已初始化的全局变量和静态变量编译时就已经分配了空间 |
.text | 一、只读存储区 -- 常量,const全局变量二、文本区 -- 程序代码,机器代码 |
0-4k保护区 |
#include<stdio.h> int a; //未初始化全局区 .bss int b=1; //已初始化全局区 .data static int c=2; //已初始化全局区 .data const int d=3; //只读数据段,也叫文字常量区 ro.data, d的值不能被修改 int main(void) { int e=4; //栈区 static int f=5; //已初始化全局区 const int g=6; //栈区,不能经过变量名修改其值,但可经过其地址修改其值 int *p=malloc(sizeof(int)) //指针变量p在栈区,但其所指向的4字节空间在堆区 char *str="abcd"; //字符串“abcd”存在文字常量区,指针变量str在栈区,存的是“abcd”的起始地址 return 0; }
内存泄漏,是因为疏忽或错误形成程序未能释放掉再也不使用的内存。内存泄漏,并非指内存内存再物理地址上的消失,而是应用程序分配某段内存后,失去了对该段内存的控制,于是形成内存的浪费。ios
使用valgrind,mtrace来检测内存泄漏c++
避免内存泄漏:git
1.事前预防型。如智能指针等。 2.过后查错型。如泄漏检测工具。github
使用智能指针,智能指针会自动删除被分配的内存,他和普通指针相似,只是不须要手动释放指针,智能指针本身管理内存释放,不用担忧内存泄漏问题面试
智能指针有:编程
其中auto_ptr c++11已经被弃用了后端
独占的智能指针,只能有一个对象拥有全部权,独占指针的是本身管理内存的,指针存在于栈空间,开辟的内存在堆空间,这里的堆空间是和智能指针绑定的,智能指针随着函数结束被销毁以前,智能指针会先去把堆里面的内存销毁api
其中涉及数组
unique_ptr智能指针
的对象 如 auto myptr = make_unique<person>();
若是但愿只有一个智能指针管理资源 就使用 unique_ptr
#include <iostream> #include <string> #include <memory> using namespace std; struct person { ~person() { cout<<"~person"<<endl; } string str; }; unique_ptr<person> test() { return unique_ptr<person> (new person); } int main() { //unique_ptr is ownership unique_ptr<person> p = test(); p->str = "hello world"; unique_ptr<person> p2 = move(p); //可使用move函数来转移全部权,转移全部权后,原来的指针就无权访问 if(!p) { cout<<"p == null" <<endl; } if(p2) { cout<<"p2 have ownership"<<endl; cout<<p2->str<<endl; } p2.reset(new person);//能够用reset函数来重置全部权,会把以前的对象全部权释放掉,从新建立一个全部权对象 if(p2->str.empty()) { cout<<"str is null"<<endl; } return 0; }
共享的智能指针,shared_ptr
使用引用计数(use_count方法),每一个shared_ptr
的拷贝都指向同一块内存,在最后一个shared_ptr被析构的时候,内存才会被释放
使用函数返回本身的shared_ptr
时,须要继承enable_shared_from_this
类,使用shared_from_this函数进行返回
注意事项:
但愿多个指针管理同一个资源就使用shared_ptr
#include <iostream> #include <string> #include <memory> using namespace std; struct person :enable_shared_from_this<person>{ string str; void show() { cout<<str<<endl; } ~person() { cout<<"~person"<<endl; } shared_ptr<person> getshared() { return shared_from_this(); } }; int main() { #if 0 shared_ptr<person> ptr(new person); cout<< ptr.use_count()<<endl; shared_ptr<person> ptr2 = ptr; cout<< ptr.use_count()<<endl; shared_ptr<person> a = make_shared<person>(); cout<< a.use_count()<<endl; a = ptr2; cout<< ptr.use_count()<<endl; shared_ptr<person> mm = a->getshared(); #endif shared_ptr<person> ptr; { shared_ptr<person> ptr2(new person); ptr2->str = "hello"; ptr = ptr2->getshared(); cout<< ptr.use_count()<<endl; } ptr->show(); return 0; }
弱引用的智能指针
是用来监视shared_ptr的,不会使用计数器加1,也不会使用计数器减1,主要是为了监视shared_ptr的生命周期,更像是shared_ptr的一个助手。weak_ptr还能够用来返回this指针和解决循环引用的问题。
shared_ptr会有循环引用的问题 ,解决方式为 把类中的shared_ptr 换成 weak_ptr便可
struct ListNode { std::shared_ptr<ListNode> _next;//std::weak_ptr<ListNode> _next; 就能够解决 std::shared_ptr<ListNode> _prev;//std::weak_ptr<ListNode> _pre; 就能够解决 ~ListNode() { cout << "~ListNode()" << endl; } }; void test_shared_ptr_cycleRef() { std::shared_ptr<ListNode> cur(new ListNode); std::shared_ptr<ListNode> next(new ListNode); cur->_next = next; next->_prev = cur; } int main() { test_shared_ptr_cycleRef(); system("pause"); return 0; }
例如上述代码案例
void shared_ptr_cycleRef(){ std::shared_ptr<LISTNODE> cur LISTNODE; std::shared_ptr<LISTNODE> next LISTNODE; cur->_next = next; next->_pre = cur; }
Cur 和 next 存在循环引用,他们的引用计数都变为 2
出了做用域以后,cur 和 next 被销毁,引用计数减 1
所以要释放cur , 就须要释放next 的 _pre,要释放next , 就须要释放cur 的 _next
valgrind的官方网址是:http://valgrind.org
valgrind被设计成非侵入式的,它直接工做于可执行文件上,所以在检查前不须要从新编译、链接和修改你的程序。要检查一个程序很简单
命令以下: valgrind --tool=tool_name program_name
valgrind --tool=memcheck ls -l
valgrind --tool=memcheck --leak-check=yes ls -l
valgrind有以下几个工具:
memcheck
memcheck
探测程序中内存管理存在的问题。
它检查全部对内存的读/写操做,并截取全部的malloc/new/free/delete
调用。所以memcheck工具可以探测到如下问题:
Memcheck 工具主要检查下面的程序错误:
cachegrind
cachegrind 是一个cache剖析器。
它模拟执行CPU中的L1, D1和L2 cache,
所以它能很精确的指出代码中的cache未命中。
它能够打印出cache未命中的次数,内存引用和发生cache未命中的每一行 代码,每个函数,每个模块和整个程序的摘要。
若要求更细致的信息,它能够打印出每一行机器码的未命中次数。
在x86和amd64上, cachegrind经过CPUID自动探测机器的cache配置,因此在多数状况下它再也不须要更多的配置信息了。
helgrind
helgrind查找多线程程序中的竞争数据。
helgrind查找内存地址,那些被多于一条线程访问的内存地址,可是没有使用一致的锁就会被查出。这表示这些地址在多线程间访问的时候没有进行同步,极可能会引发很难查找的时序问题。
在申请内存时
realloc是在C语言中出现的,c++已经摒弃realloc函数,realloc函数分配一块新内存的时候,会把原内存中的内存copy到新内存中,经过memmove的方式
关键字和语法
编译器能够根据初始化来推导数据类型,不能用于函数传参和以及数组类型推导
一种特殊类型的字面量,能够被转成任意的其余类型
初始化类的列表
能够实现移动语义和完美转发,消除两个对象交互时没必要要的拷贝,节省存储资源,提升效率
新增容器
智能指针,内存管理
新增 shared_ptr、weak_ptr用于内存管理
多线程
用于多线程互斥
其余
能够经过捕获列表访问上下文的数据
#ifndef
做用:相同的两个文件不会被重复包含。
优势:
缺点:
做用:物理上的同一个文件不会被重复包含。
优势:
缺点:
“一种”
(a kind of )继承 (如 男人 继承 人类)
“一部分”
(a part of)组合(如 组合 眼 耳 口 鼻 -> 头)
继承与组合区别
继承
优势:
缺点:
组合
优势:
缺点:
好处:简化结构和程序通用性的问题,也是实现面向对象编程的一种途径
做用:
inline函数是C++引入的机制,目的是解决使用宏定义的一些缺点。
用它替代宏定义,消除宏定义的缺点。
朋友们,你的支持和鼓励,是我坚持分享,提升质量的动力
好了,本次就到这里,下一次 GO的并发编程分享
技术是开放的,咱们的心态,更应是开放的。拥抱变化,向阳而生,努力向前行。
我是小魔童哪吒,欢迎点赞关注收藏,下次见~