《后台开发核心技术与应用实践》(二)

10 篇文章 0 订阅
10 篇文章 2 订阅

3. 常用STL的使用

3.1. string

(1)string类的实现(使用strlen、strcpy、strcat、strcmp等,注意判NULL)。
(2)C++字符串和C字符串的转换:data()以字符形式返回字符串内容,但不添加’\0\;c_str()返回一个以’\0’结尾的字符数组;copy()把字符串内容复制或写入既有的c_string或字符数组内。
(3)string和int互转:snprintf()、strtol/strtoll/strtoull.
(4)常用成员函数:capacity()、max_size()、size()、length()、empty()、resize()

3.2. vector

(1)容器大小size()指元素个数,容量capacity()指分配的内存大小
(2)遍历:for(int i=0;i<a.size();++ifor(iter=ivector.begin();iter!=ivector.end();iter++)for_each
(3)查找find()、删除erase()/pop_back()、增加insert()/push_front(),注意for 循环遍历删除时的坑:for语句条件里删除元素时,返回值指向已删除元素的下一个位置,不是删除元素时则直接++
(4)reserve()提前设定容量大小;swap()强行释放vector所占内存

3.3. map

(1)map内部自建一颗红黑树,具有对数据自动排序的功能。须回顾二叉树、红黑树。。。
(2)插入pair数据、数组方式插入、数据方式覆盖插入
(3)遍历:利用前向迭代器、利用反向迭代器、数组方式
(4)查找find()、删除erase()、排序less/greater

3.5. set

(1)创建、插入元素、删除元素、查找元素等。。

4.编译

4.1.编译与链接

(1)过程:预处理(prepressing),编译(compilation),汇编(assembly),链接(linking)
过程
(2)预处理:主要处理那些源代码文件只能够的以”#”开始的预编译指令。比如“#include”、“#define”,过滤所有注释,添加行号,保留#pragma编译器指令等
(3)编译:扫描(词法分析)、语法分析、语义分析、源代码优化、代码生成和目标代码优化
编译
(4)链接:把各个模块之间相互引用的部分都处理好,使得各个模块之间能够正确的衔接。
原理:把一些指令对其他符号地址的引用加以修正。链接过程主要包括了地址和空间分配、符号决议和重定位等
链接
(5)静态链接库和动态链接库

1.动态链接库有利于进程间资源共享;
2.动态链接库升级容易,用静态库则需要重新编译;
3.许多进程或应用程序可在磁盘上共享动态库的一个副本,可节省内存和减少交换操作,节省磁盘空间;
4.静态链接库在编译的时候将库函数装载到程序中,执行速度更快。

(6)g++和gcc

1.后缀为.c的,gcc将其当作C程序,而g++当作是C++程序;后缀为.cpp的,两者都认为是C++程序;
2.编译阶段,g++会自动调用gcc,两者等价;但因为gcc不能自动和C++程序使用的库链接,所以通常用g++来完成链接,所以通常直接用g++编译、链接;
3.extern”C”与gcc/g++并无关系。

4.2.makefile的撰写

(1)书写规则,第一部分为依赖关系,第二部分为生成目标的方法:

target  : prerequisites 
<tab>command
<tab>command

target也就是一个目标文件,可以是.o文件,也可以是执行文件,还可以是一个标签(Label)。
prerequisites就是,要生成那个target所需要的文件或是目标。
command也就是make需要执行的命令(任意的Shell命令)。这里要注意的是在命令前面要加上一个tab键,不是空格,是按一个tab键按出来的空格。
(2)make clean用于清除编译产生的二进制文件,保留源文件:

clean:
    @echo "cleaning project"
    -rm main *.o
    @echo "clean completed"

在rm命令前面加了一个小减号的意思就是,也许某些文件出现问题,但不要管,继续做后面的事
(3)变量,用$(objects)的方式来使用
(4)$@扩展成当前规则的目的文件名;$<扩展成依靠列表中的第一个依靠文件;$^ 扩展成整个依靠列表(除掉重复文件名)

4.3.目标文件

(1)目标文件:源代码编译后但是没有进行链接的那些中间文件,比如win下的.obj文件、linux下的.o文件,与可执行文件的内容以及格式很类似。

目标文件中的内容至少有编译后的机器指令代码、数据。还包括连接时所需要的一些信息,比如符号表、调试信息、字符串等。一般,目标文件会将这些信息按照不同的属性进行分段(其实就是多个一定长度的区域)。

这里写图片描述
这里写图片描述
(2)ELF文件主要由文件头(ELF header)、代码段(.text)、数据段(.data)、.bss段、只读数据段(.rodata)、段表(section table)、符号表(.symtab)、字符串表(.strtab)、重定位表(.rel.text)如下图所示:
这里写图片描述
(3)代码段与数据段分开的原因:

1.权限分别管理。对进程来说,数据段是可读写的,指令段是只读的。这样可以防止程序指令被改写。
2.指令区与数据区的分离有助于提高程序的局部性,有助于对CPU缓存命中率的提高。
3.当系统运行多个改程序的副本的时候,他们对应的指令都是一样的,此时内存只需要保留一份改程序的指令即可。当然,每个副本进程的数据区域是不一样的,他们是进程私有的

这里写图片描述
(4)阅读ELF文件的工具readelf;获得二进制文件里符号的工具nm;减少目标文件大小的工具strip

5.调试

5.1.strace

(1)通过跟踪系统调用观察程序在后台所做的事情
(2)跟踪信号传递
(3)统计系统调用

5.2.gdb

(1)常用调试命令

命令描述
backtrace(或bt)查看各级函数调用及参数
finish连续运行到当前函数返回为止,然后停下来等待命令
frame(或f) 帧编号选择栈帧
info(或i) locals查看当前栈帧局部变量的值
list(或l)列出源代码,接着上次的位置往下列,每次列10行
list 行号列出从第几行开始的源代码
list 函数名列出某个函数的源代码
b 行号在第几行设置断点
b 函数名在函数处设置断点
next(或n)执行下一行语句
print(或p)打印表达式的值,通过表达式可以修改变量的值或者调用函数
quit(或q)退出gdb调试环境
set var修改变量的值
start开始执行程序,停在main函数第一行语句前面等待命令
step(或s)执行下一行语句,如果有函数调用则进入到函数中

(2)用gdb分析、定位coredump文件

5.3.top

实时显示系统中各个进程的资源占用状况
top
使用参考

5.4.ps

列出刚刚那一时刻正在运行的进程快照

参数功能
a显示所有进程
-a显示同一终端下的所有程序
-A显示所有进程
c显示进程的真实名称
-N反向选择
-e等于“-A”
e显示环境变量
f显示程序间的关系
-H显示树状结构
r显示当前终端的进程
T显示当前终端的所有程序
u指定用户的所有进程
-au显示较详细的资讯
-aux显示所有包含其他使用者的行程
-C<命令>列出指定命令的状况
–lines<行数>每页显示的行数
–width<字符数>每页显示的字符数
–help显示帮助信息
–version显示版本显示

5.5.Valgrind

(1)Valgrind包括如下工具:

1.Memcheck。这是valgrind应用最广泛的工具,一个重量级的内存检查器,能够发现开发中绝大多数内存错误使用情况,比如:使用未初始化的内存,使用已经释放了的内存,内存访问越界等。这也是本文将重点介绍的部分。
2.Callgrind。它主要用来检查程序中函数调用过程中出现的问题。
3.Cachegrind。它主要用来检查程序中缓存使用出现的问题。
4.Helgrind。它主要用来检查多线程程序中出现的竞争问题。
5.Massif。它主要用来检查程序中堆栈使用中出现的问题。
6.Extension。可以利用core提供的功能,自己编写特定的内存调试工具

(2)linux下典型C程序内存空间布局:
这里写图片描述
(3)堆/栈的区别

1)申请方式: 栈区内存由系统自动分配,函数结束时释放;堆区内存由程序员自己申请,并指明大小,用户忘释放时,会造成内存泄露,不过进程结束时会由系统回收。
2)申请后系统的响应: 只要栈的剩余空间大于所申请的空间,系统将为程序提供内存,否则将报异常提示栈溢出;堆区,空闲链表,分配与回收机制,会产生碎片问题(外部碎片)–>(固定分区存在内部碎片(分配大于实际),可变分区存在外部碎片(太碎无法分配))。
3)申请大小的限制:栈是1或者2M,可以自己改,但是最大不超过8M;堆,看主机是多少位的,如果是32位,就是4G
4)申请效率:栈由系统自动分配,速度较快,程序员无法控制;堆是由new分配的内存,一般速度较慢,而且容易导致内存碎片,但是用起来方便!
5)存储内容:栈,函数调用(返回值,各个参数,局部变量(静态变量不入栈));堆,一般在堆的头部用一个字节存放堆的大小,堆中的具体内容由程序员安排。
6)存取效率的比较:栈比堆快,Eg :char c[] = /”1234567890/”;char *p =/”1234567890/”;读取c[1]和p[1],c[1]读取时直接吧字符串中的元素读到寄存器cl中,而p[1]先把指针值读到edx中,再根据edx读取字符,多一次操作。
7)管理方式不同:栈,数据结构中的栈;堆,链表
8)生长方向:栈,高到低;堆,低到高

(4)Valgrind安装/使用
使用参考

《后台开发核心技术与应用实践》(一)
《后台开发核心技术与应用实践》(二)
《后台开发核心技术与应用实践》(三)
《后台开发核心技术与应用实践》(四)

后台开发核心技术应用实践 作者:徐晓鑫 著 出版日期:2016年08月06日 封面宣传语:腾讯云平台技术总监黄世飞、Facebook对外支付项目主程张子兴、微软软件工程师彭可竞、阿里巴巴资深算法工程师周乐、百度大数据高级测试工程师畅晋联袂推荐;围绕后台开发需要掌握的核心技术,从多个方面、多个角度进行了阐述,覆盖了该领域的几乎所有内容;充分抓住本质并结合实践,文字通俗易懂,可操作性强 出版书名:后台开发核心技术应用实践 作者:徐晓鑫 著 封底文字 专家评价 后台开发是一个“历史悠久”的领域,同时也是一个沉淀深厚,高技术价值的领域。本书清晰、严谨、务实的风格显示出晓鑫对该领域知识的深刻理解。 ——张子兴 Facebook对外支付项目主程,美国加州MenloPark 每一位从事后台开发的专业人士都需要一本后台开发指南。对每一位想要认真从事该领域工作的人来说,本书是一本绝对必读的书籍。 ——彭可竞 微软软件工程师,美国华盛顿州Redmond 本书是作者多年后台开发、架构和研究的精华。书中用通俗的文字、详尽的示例代码,结合实际工作中的案例,讲述了后台开发方方面面的知识,内容丰富。对于从事后台开发的人员,这是一本很好的由浅入深的学习书籍。 ——周乐 阿里巴巴资深算法工程师,北京望京 使用C++语言进行后台开发有一定的门槛,本书可以很好地帮助你跨过这个“门槛”。 ——畅晋 百度大数据高级测试工程师,北京上地 前勒口 互联网网民日益剧增,各种应用层出不穷,各项技术更新不断。单是游戏行业,近几年就经历了从端游、页游到手游的巨大变迁,客户端更新迭代之快,始料未及。而后台开发中使用到的技术,却变化不是很大。让服务性能更高、处理能力更强、安全性更好,是后台开发工程师永恒的主题。 后台开发中用到的技术,深而广,需要读的“大部头”很多,光是Richard Stevens的APUE,UNP,TCP/IP详解就够读个半年以上。读者通过阅读本书,可以从实践出发,快速由浅入深地进入后台开发领域。在读完本书,有了实践的经验之后,再去阅读大师们的著作,会更有体会,更懂得如何欣赏。 读书的最高境界莫过于“把书读薄,把书读厚”。本书文字通俗易懂,让你更快地“读薄”,同时又涉及较多的核心知识点,顺着这些知识点,读着读着也发觉“读厚”了。 后勒口 徐晓鑫,腾讯资深软件研发工程师,先后在腾讯游戏之洛克王国、QQ会员、QQ秀等项目工作,精通后台开发各种技术,实战经验丰富。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值