- 博客(55)
- 资源 (1)
- 收藏
- 关注
原创 动态链接(二)
5. 动态链接相关结构首先装载方面和静态链接下的装载基本无异,唯一不同的是装载完之后控制权交给动态链接器,而不是可执行文件的入口。系统加载完动态链接器之后将控制权交给动态链接器的入口地址,接着动态链接器进行一系列的初始化及链接工作,完成之后将控制权交给可执行文件的入口,开始执行。5.1 .interp段在动态链接的ELF可执行文件中,存在.interp段,专门说明需要用到的动态链接器的...
2018-12-05 15:04:02
408
原创 动态链接(一)
1. 为什么要动态链接静态链接的缺点:(1)内存和磁盘空间:比如有两个程序,目标文件分别为Program1.o,Program2.o,并且都用到Lib.o这个模块。静态链接生成可执行文件Program1,Program2时,它们都分别存有Lib.o模块的一个副本。当同时运行Program1和Program2时,Lib.o在磁盘和内存中都有两个副本。可见会造成内存和磁盘空间的浪费。(...
2018-12-04 12:13:46
532
原创 可执行文件的装载与进程
1. 进程虚拟地址空间每个进程拥有自己独立的虚拟地址空间,这个虚拟地址空间由cpu位数决定,硬件决定了地址空间的最大理论上限,即硬件的寻址空间大小。比如32位的硬件平台决定了虚拟地址空间的地址为0到2^32-1,即0x00000000~0xFFFFFFFF,共4GB。而64位的硬件平台具有64位寻址能力,虚拟地址空间达到2^64字节,即17179869184GB。从程序角度,比如可以判断C...
2018-11-29 10:43:29
408
原创 Windows PE/COFF
1.Windows的二进制文件格式PE/COFF在32位Windows平台下,微软引入了一种叫PE(Protable Executable)的可执行格式。PE文件格式和ELF都是由COFF格式发展而来的。而对于VISUALC++编译器产生的目标文件仍然使用COFF格式。由于PE是COFF的一种扩展,所以它们的结构在很大程度上相同,甚至跟ELF文件的基本结构也相同。即Windows下目标文件默认...
2018-11-20 21:14:55
757
原创 静态链接
链接就是指将多个目标文件链接在一起并最终形成一个可执行文件。两个示例源码:a.cextern int shared;int main() { int a=100; swap(&a,&shared);} b.cint shared=1;void swap(int *a,int *b) { int c; c=*a; *a=*b; *b=...
2018-11-15 20:39:05
2805
原创 解析目标文件
1.目标文件是什么编译阶段分为预处理,编译,汇编,链接。Linux下汇编之后生成的.o文件就是目标文件,此时的目标文件经过链接之后才会生成最后的可执行文件。实际上,目标文件和可执行文件的结构基本上是相同的,区别就是目标文件中对一些符号的引用和地址还没有确定,只有等到链接之后才能确定。可以把目标文件和可执行文件看成是同一类型的文件。2.目标文件的格式Windows下可执行文件的格式是PE...
2018-11-08 15:55:46
462
原创 Windows下线程的同步
内核对象首先介绍内核对象的概念。应用程序在运行过程中会创建各种资源,如进程,线程,文件,互斥量等等。这些资源均由操作系统管理。操作系统管理这些资源的方式就是:记录这些资源的相关信息,会在其内部生成数据块。每种资源需要维护的信息不同,因此每种资源拥有的数据块格式也不同。这类数据块就是“内核对象”。即使资源的创建请求是在进程内部完成的,但内核对象的所有者并不是该进程,而是内核即操作系统。内核对象的创建...
2018-04-02 14:49:14
217
原创 Linux下多线程服务器端的实现
Linux下多线程编程时,编译命令需要加上-lpthread选项。g++ test.cpp -o test -lpthread线程的创建线程具有单独的执行流,所以会有自己的main函数。创建线程的函数如下:int pthread_create(pthread_t * restrict thread,const thread_attr_t * restrict attr,void *(* start...
2018-03-27 15:00:36
370
1
原创 epoll讲解
实现I/O复用技术除了可以使用select,还可以使用epoll。先说一下select的缺点,每次调用完select之后,一般都会有一个循环,遍历全部文件描述符,找出发生事件的那一个,可见时间效率并不高。因此,select函数一般适用于服务器端接入者少,要求有兼容性的情况下。兼容性是因为各大操作系统都支持select函数。相反,epoll则可以将发生事件的所有文件描述符都集中在一起,因此遍历这个集...
2018-03-22 20:56:49
263
原创 select()函数用法
select()函数是实现服用服务器端的一种方法。这里介绍Linux环境下select()函数的用法,Windows下的大同小异。select函数的功能select函数可以同时监视多个文件描述符,并且可以监视三种事件。一旦某个文件描述符所指的对象发生了相应事件,就可以进行相应的处理。监视的三种事件:(1)是否有对象需要接受数据。(2)是否有对象需要传输数据。(3)是否有对象发生了异常。select...
2018-03-20 11:51:15
3321
原创 Ubuntu16.04编译Linux内核
本文介绍在Ubuntu中编译Linux内核并添加新的启动项信息。第一步:下载内核源码并解压内核源码可以在官网下载:点击打开链接笔者用的内核版本是4.14的。把下载好的内核源码放在/usr/src/kernel目录下,没有这个目录的话可以自己创建。通过以下命令把内核源码解压,后面跟的是源码文件名。tar xvJf xxxxxx.tar.xz第二步:配置编译选项配置编译选项有多种方法:(1)make...
2018-03-14 23:47:33
5236
原创 Codeforces 946D Timetable
题意:有n天,每天有m个小时,“1”代表有课,“0”代表没课。Ivan可以选择性地逃掉k节课,问如何逃课才能使得Ivan呆在学校的总时间最短。每天呆在学校的时间为第一节课到最后一节课的时间,例:0011010,则呆在学校的时间为4个小时。输入:n,m,k,接着是一个n行m列的矩阵。1<=n,m<=500,0<=k<=500。题解:注意到数据量很小,可以想到进行三层循环都不会...
2018-03-12 11:42:08
347
原创 用Java实现文本编辑器
源码里有注释:import java.awt.*;import java.awt.event.*;import java.io.*;import javax.swing.*;import javax.swing.text.*;//简单的文本编辑器public class Editor extends JFrame { public JTextPane textPane = new...
2018-02-14 10:25:06
22316
4
原创 socket()函数介绍
socket函数创建套接字:SOCKET socket(int af, int type, int protocol); 成功时返回套接字句柄,失败时返回INVALID_SOCKET。句柄其实就是标识符,唯一地标识某个东西。第一个参数套接字通信中的协议有一些分类。第一个参数传递套接字中使用的协议分类信息,此协议分类信息称为协议族。下面列出几个协议族:(1)PF_INET。IPv4互联网协议族。(2...
2018-02-13 22:47:30
1728
1
原创 window套接字编程
套接字什么是套接字?套接字(socket)是操作系统提供的用来进行网络数据传输的软件设备。即使对网路数据传输原理不太熟悉,也可以通过套接字完成数据传输。操作系统提供相应的函数,windows和linux提供的函数有一些差异,但大致思想是一样的。下面介绍windows的几个函数:socket函数创建套接字:SOCKET socket(int af, int type, int protocol);成...
2018-02-12 21:31:58
1782
原创 C++输入输出迭代器
C++输入输出可以使用cin,cout,也可以使用C语言的scanf和printf。这里介绍使用输入输出迭代器进行输入输出。迭代器迭代器代表广义指针,可以完成常规指针的所有操作。C++的STL定义了5中迭代器:(1)输入迭代器。(2)输出迭代器。(3)正向迭代器。(4)双向迭代器。(5)随机访问迭代器。这些包含在头文件iterator中。输入迭代器输入迭代器指向某个输入流,因此可以
2018-02-06 14:36:22
2694
原创 C++智能指针
对于常规指针,如果指向的是动态分配的内存,则必须要记得使用delete。智能指针模板类正是用来解决这个问题的,解决程序员”不记得“的毛病。智能指针是行为类似于常规指针的类对象。既然是类对象,就会有析构函数,智能指针的析构函数就是执行了delete操作。所以一当智能指针无效时,会自动调用它的析构函数,把它指向的内存也一并释放掉。这里介绍三个智能指针模板类:(1)auto_ptr。(2)unique_
2018-02-04 16:10:45
558
原创 C++异常
调用abort()调用abort()将使程序异常终止。因此可以在程序中添加异常测试代码,如果检测到了异常,就调用abort()使程序终止。以下这个例子是输入a和b,输出a/b的结果。在函数中检测除数是0的情况,如果除数是0,代表异常。#include#includeusing namespace std;const double esp = 1e-20;double myDi
2018-02-03 16:51:31
271
原创 C++类的三种继承
各种继承方式 公有继承 保护继承私有继承公有成员变成派生类的公有成员派生类的保护成员派生类的私有成员保护成员变成派生类的保护成员派生类的保护成员派生类的私有成员私有成员变成还是基类的私有成语,只能通过基类接口访问还是基类的私有成语,只能通过基类接口访问还是基类的私有成语,只能通过基类接口访问
2018-02-01 16:03:22
233
原创 C++静态联编和动态联编
所谓联编就是:程序调用函数时,编译器通过某种方法确定具体要执行的代码块的过程。分为静态联编和动态联编。在C语言中,这显得很简单,因为每个函数名对应于不同的函数,所以根据函数名就可以确定具体要执行的代码块。而在C++中,有了函数重载,类继承中的虚函数等特性之后,这个过程就变得很复杂了。在编译过程中进行联编的就是静态联编,在程序运行时才确定要执行哪个代码块的话就是动态联编。在类继承中指针和引用
2018-01-31 16:57:51
419
原创 win32汇编窗口中添加第一个按钮
.386.model flat,stdcalloption casemap:noneinclude windows.incinclude gdi32.incincludelib gdi32.libinclude user32.incincludelib user32.libinclude kernel32.incincludelib kernel32.lib.datahI
2017-12-29 11:27:06
639
原创 Codeforces 899D Shovel Sale
题意:给一个数n(2题解:令sum代表n+n-1,如果sum是99999...99这种形式的话,则答案是1。如果不是,假设sum有len位,则x是len-1,x是上面提到的x。则此时枚举最高为从0到8,分别得到09999..9,19999..9,29999...9。。。。。89999...9。令这些数是p。如果p如果p>n+1&&p否则如果p>n+n-1,对答案无贡献。
2017-12-26 11:48:55
246
原创 C++类的自动转换和强制类型转换
通过构造函数来转换如果有这样的构造函数:Node(int _x);则可以有这样的语句:Node a=2;这条语句实际上将使用2作为构造函数的参数创建临时变量,然后将该变量复制到a中,由于这一步是自动进行的,所以称为隐式转换。注意只有一个参数的构造函数(或者有多个参数,但除了第一个,其他的参数都有默认值)才能用来转换。可以用于隐式转换的情况(前提是有满足条件的构造函数):
2017-12-18 21:10:57
491
原创 C++随机数
头文件cstdlib中包含了rand()和srand()的原型。而ctime包含了time()的原型。rand()函数返回从0到某个数的随机数。如果将它模一个数,即rand()%x,得到的是从0到x-1的随机数。这种方法得到是伪随机数,因为在其内部的算法作为seed(种子)的数总是不变的,因此每次运行程序得到的随机数序列都相同。x=rand()%360;srand()函数提供设置种子的
2017-12-18 20:15:22
340
原创 win32汇编第一个窗口程序
窗口程序的运行过程(1)得到应用程序的句柄(GetModuleHandle)。(2)注册窗口类(RegisterClassEx),在注册之前,要填写RegisterClassEx的参数WNDCLASSEX结构。(3)建立窗口(CreateWindowEx)。(4)显示窗口(ShowWindow)。(5)刷新窗口客户区(UpdateWindow)。(6)进入无限的消息获取和处理的循环。首先获取消息(...
2017-12-17 20:06:03
764
原创 Codeforces 903D Almost Difference
题意:定义一个函数给定一个含有n个数的数组a,要求求出所有d(ai,aj)的和,其中1其中1题解:最然ai最大为1e9,但最多也就只有2e5个数,因此可以先离散化再建线段树。线段树里每个节点存有数的和还有数的个数。遍历每个数,对于当前的这个数ai,求出比它小的数的和sum和个数count,则count*ai-sum加到结果里,其中注意ai在线段树的前一个叶子节点是不是a
2017-12-15 13:15:56
244
原创 运算符重载
C++可以通过运算符重载来完成用户定义类型的运算。具体语法就是把函数名换成operator@,其中@代表特定的运算符。#include#includeusing namespace std;class NODE{private: int x, y;public: NODE(int _x = 0, int _y = 0) { x = _x; y = _y; }
2017-12-10 12:10:22
208
原创 类里定义常量和枚举
作用域为类的常量如果要在类里定义常量#include#includeusing namespace std;class NODE{private: int val; const int p = 1;};int main(){ return 0;}这样是编译会报错(在C++11中是可允许的,但早期的版本不支持)。因为类声明只是描述了对象的形式,并没有创建对象
2017-12-09 11:56:49
1279
原创 名称空间
传统的C++名称空间先说以下三个基本概念:声明区域,潜在作用域,作用域。声明区域:即变量可以声明的区域。如全局变量的声明区域就是全局的,代码块里的变量的声明区域就是该代码块。潜在作用域:在该变量的声明区域中,从该变量声明的位置起,到声明区域结束,都是该变量的潜在作用域。作用域:变量并非在起潜在作用域的所有地方都可见,比如会被另一个被嵌套的代码块中的同名变量给覆盖掉。因此,变量可见的
2017-12-05 11:54:26
212
原创 变量的存储持续性,作用域和链接性
存储持续性存储持续性分为自动存储持续性,静态存储持续性,动态存储持续性。自动存储持续性:在函数中或者代码块中定义的变量的存储持续性是自动的。执行函数或代码块时,变量被创建,执行完之后,该变量使用的内存被释放。静态存储持续性:在函数外定义的或者用static关键字定义的变量的存储持续性是静态的。它在整个程序运行过程中都存在。动态存储持续性:用new分配的内存,直到用delete才会被
2017-12-03 21:11:53
324
原创 Codeforces896A Nephren gives a riddle
题意字符串f0是"What are you doing at the end of the world? Are you busy? Will you save us?"。字符串 fi 是 "What are you doing while sending "fi - 1"? Are you busy? Will you send "fi - 1"?" 。先输入q(1
2017-12-03 14:10:01
271
原创 Codeforces897B Chtholly's request
题意给你k和p,k最大是1e5,p最大是1e9。问你前k小的偶数长度的回文数的和,再模p。例如,11,22,1221,就是偶数长度的回文数。思路很容易想到,从1枚举到k,把每个数反向复制拼接起来,就是前k小的偶数长度的回文数。比如前10小是:11,22,33,44,55,66,77,88,99,1001。这分别是1 2 3 4 5 6 7 8 9 10前10个数反向复制拼接起来得到
2017-12-03 13:59:50
258
原创 函数模板
#include#includeusing namespace std;templateT add(T a, T b);int main(){ int a, b; cin >> a >> b; double c, d; cin >> c >> d; cout << add(a, b) << endl; //根据实参的具体类型创建相应的函数 cout << add(
2017-11-30 20:00:47
233
原创 引用类型
创建引用变量引用是C++新增的特性,它能实现在函数调用指针能实现的功能,即通过修改参数的值从而修改实参的值。创建引用的语句: int a = 1; int &b = a;&在这里不是取地址的意思,而是类型标识符的一部分。表示变量b是一个引用。这样声明的结果是a和b指向相同的内存单元,即b是a的别名。两者完全等效。另外,引用变量必须初始化。 int a = 1; int &b =
2017-11-28 09:40:47
157
原创 内联函数
浅谈程序内部编译的最终产品是可执行程序,由一堆机器指令组成。运行程序时,操作系统将这些机器指定载入内存,每条指令都有自己的地址,随后操作系统逐步执行这些指令。执行遇到分支或者循环等其他条件时,将会跳到特定指令地址处。常规函数调用也是使程序跳到特定的指令处(被调用函数的首地址),并在函数结束时返回。更详细的过程是,遇到函数调用指令时,程序在函数调用后,立即存下当前指令地址,如果还需要传参数,则参
2017-11-25 11:40:44
224
原创 C++指针和const
指针指向的值为常量 int a = 1; const int *p = &a; //指针p指向的值为常量,不能通过指针p来修改值 *p = 2; //这是错误的 a = 2; //a本身为普通变量,这是允许的值得一提的是,非const变量的地址可以同时赋给const指针和非const指针,而const变量的地址只能赋给const指针不能赋给非const指针。 int a
2017-11-23 08:48:09
177
原创 C++函数原型
函数原型即在调用某个函数前,需事先声明的一条语句,它和函数定义的头部一致,参数变量名可以省略。首先说一下C++函数是如何返回值的。通常,函数通过将返回值复制到指定的cpu寄存器或内存单元中。然后调用程序或调用函数(是指调用了该函数的函数)将查看该内存单元。函数原型将返回值类型告知调用程序,而函数定义确定具体返回值的类型,显然这两者应该保持一致。为什么需要原型原型描述了函数到编译器的接口
2017-11-21 11:24:19
1075
原创 C++简单文件输入输出
简单文件输入输出使用文件输入输出需要包括头文件fstream。该头文件里有用于处理输入的类ifstream和输出的类ofstream。以下给个例子:#include#includeusing namespace std;int main(){ ifstream in; //in可以用cin的所有方法 ofstream out; //out可以用cout的所有方
2017-11-15 19:42:30
412
原创 cin读取数字时遇到字符的情况
cin读取数字时遇到字符当定义一个int变量,用cin输入时,如果输入的是一个字符,会发生以下4中情况:1.n的值变成02.不匹配的输入被留在输入流中3.cin对象的一个错误标记被设置,即cin.fail()返回true4.对cin的方法调用返回false,即(cin>>n)返回的是false#includeusing namespace std;int main()
2017-11-14 12:11:36
6864
4
原创 字符函数库cctype
字符函数库cctype该函数库里包含了一些与字符相关的,非常方便的一些函数,可以简化程序员的工作。例如,当判断一个字符是否是字母时,以下两条语句是等价的,其中第二条语句用到了字符函数库里的函数。#includeusing namespace std;int main(){ char ch; cin>>ch; if(ch>='a'&&ch='A'&&ch
2017-11-14 11:17:09
226
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人