博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【C/C++学院】0724-堆栈简单介绍/静态区/内存完毕篇/多线程
阅读量:6733 次
发布时间:2019-06-25

本文共 8051 字,大约阅读时间需要 26 分钟。

【送给在路上的程序猿】

对于一个开发人员而言,可以胜任系统中随意一个模块的开发是其核心价值的体现。

对于一个架构师而言,掌握各种语言的优势并能够运用到系统中。由此简化系统的开发。是其架构生涯的第一步。

对于一个开发团队而言。能在短期内开发出用户惬意的软件系统是起核心竞争力的体现。

每个程序猿都不能固步自封。要多接触新的行业。新的技术领域,突破自我。

堆栈简单介绍、内存完毕篇

Const是一个伪常量

#include
#include
#define N 10 //CPU产生,10 . 1010//const是伪常量,限定编译器尽量不直接改动void main(){ //int a=10; int *p=&a; const int num = 10;//避免直接赋值的改动,不能够避免间接赋值的改动 //num=1; const int *p1 = #//创建指针指向const int int *p2 = (int *)p1; *p2 = 100; printf("%d", num); getchar();}void main1(){ //&N; //N = 3; //num = 3; int data[N]; //int data[num];}

代码区是仅仅读的

函数名称就是函数的地址

#include
#include
void gogogo(){ printf("AAAAA\n\n\n\n");}void main1(){ printf("%p", gogogo);//函数名存放函数的地址 //gogogo = gogogo;代码区仅仅能读不可写 //void gogogo(); //void ()(); gogogo();//直接调用 void(*p)()=gogogo; p();//间接调用 getchar();}void main(){ char *p = "ABCDEFG";//p存储常量字符串的地址 printf("%d,%d\n", sizeof(p), sizeof("ABCDEFG"));//4 ,8 printf("\n%p", &p);//查看指针变量的地址 printf("\n%p", p);//查看字符串的地址 //*p = 'a';//代码区仅仅能读,常量字符串在代码区 getchar();}

堆的空间,由程序猿控制

#include
#include
#include
//内存分配,malloc calloc,reallocvoid test(){ int *p = (int *)malloc(sizeof(int)* 10);//指针除了地址。更重要的是指针的类型, printf("%p\n", p);//打印地址 int num = 0; for (int *px = p; px < p + 10; px++) { *px = num;//对内容赋值 printf("%p,%d\n", px, *px);//打印地址还有数据 num++; }}void mainA(){ test(); test();//调用了2次函数,而内存空间是不一样的地址 system("pause");}void mainB(){ unsigned long long ll = 1024 * 1024 * 1024;//ll 2^64-1 鲸吞 ll *= 1; void *p = malloc(ll); if (p == NULL) { printf("内存分配失败"); } else { printf("成功"); } system("pause");}void main(){ while (1)//蚕食 { //内存一定要及时释放 void *p = malloc(1024*1024*100);//p, 栈 *(p+3)地址指向的内容 Sleep(3000); }}

堆栈的生长方向

栈是连续的,向上增长。堆是链接的,向下增长。

通过打印的地址,能够进行验证。

#include
#include
void main(){ void *p1 = malloc(10); //p1,p2栈上 void *p2 = malloc(20); printf("%p,%p", &p1, &p2);//地址在栈上 printf("\n%p,%p", p1, p2);//堆区 getchar();}

函数指针外挂

外挂原理,使用dllinject工具,给进程打针。

后期能够自己实现这个工具。

打开任务管理器的时候,能够直接跳转跟踪到进程。

利用打针的技术。能够实现移花接木的手段。比方,弹出一个对话。360警察哥哥,淘宝网银风险等。

#include
#include
#include
int num = 100;void add(int x);void add(int x){ num += x;//加血}void msg(){ MessageBoxA(0, "1", "2", 0);}void main(){ printf("add=%p,msg=%p\n", add,msg); while (1) { printf("%d\n", num); Sleep(5000); }}
#include
#include
//导出函数。能够载入的时候调用_declspec(dllexport) void go(){ //函数指针类型必须一致,否则无法调用成功 //int ** 变量名挖掉就是类型 //间接调用的方式调用函数。依据地址来调用 void(*p1)(int a) = (void(*)(int a)) 0x2c10eb; p1(10); void(*p2)() = (void(*)())0x2c111d; p2(); //这里加上自己的猥琐代码,能够移花接木,唬住门外汉。}

寄存器变量

C和汇编的混合编程

#include
#include
void main1(){ int a = 1; int b = a + 1; //a + 1 = 2; b = a + 2; b = a + 3; getchar();}void main2(){ //register int a = 3; //&a;//地址是内存的地址,CPU没有地址 int a = 10; int b;//b=a+5; _asm { mov eax, a add eax, 5 mov b,eax } printf("%d", b); getchar();}

利用栈变量,卡死cpu,给进程打针实现恶搞。

#include
#include
#include
//导出函数。能够载入的时候调用_declspec(dllexport) void go(){ MessageBoxA(0, "你的360云盘存放的岛国大片被网络警察所监督", "请自首", 0); while (1) { double db[1024 * 100]; }}

栈的大小

#include
#include
void main2x (){ int a[1024*300];//1M=1024*1024 栈的大小编译器决定 //无法使用较大内存, //用完了就立马回收 getchar();}void main(){ while (1) { //注入进程,卡死CPU,卡死内存 double db[1024 * 200]; void *p = malloc(1024 * 1024); }}

静态区、内存完毕篇

函数參数的入栈顺序,从右向左

#include
#include
void main(){ int a=4; printf("%d,%d", a, a++);//參数压栈的顺序从右向左 //5, 4 getchar();}#include
#include
void main(){ int a=4; printf("%d,%d", a, ++a);//參数压栈的顺序从右向左 //5, 5 getchar();}

全局static变量,//限定仅仅有本C文件訪问

局部static变量,仅仅会初始化一次。

#include
void main(){ for (int i = 0; i < 10; i++) { int a = 10;//用完就回收 static int b = 10;//与程序共存亡,静态局部变量 。编译的时候就初始化了。仅仅会初始化一次 a += 1; b += 1; printf("%d,%d\n", a, b); } getchar();}void main2(){ for (int i = 1; i <= 100; i++) { static int res = 0;//仅仅会初始化一次 res += i; printf("%d\n", res); } //res = 3;//程序污染 getchar();}

变量的作用域

#include
#include
//int a = 10;//int a = 10;//全局变量,声明+赋值=定义int a;//声明 定义仅仅能有一个,声明能够多个int a;int a = 10;//定义void main(){ /* int a = 10;重定义 int a = 10;*/ /*int a; 对于局部变量来说。不管是否赋值都是定义 int a;*/}

静态区与栈区,静态区与程序共存亡,静态区分配优先于main函数

栈区。重复回收,重复释放

静态区与全局变量

#include
#include
int num = 10;//静态区//静态区与栈区。静态区与程序共存亡。静态区分配优先于main函数//栈区,重复回收,重复释放void test(){ int data = 3;//栈区 printf("%p,%p\n", &num, &data); num = 101; data = 34; printf("\n");}void main(){ test(); printf("\n"); test(); printf("\n"); system("pause");}

全局变量

#include
#include
int a;int a;int a;//未定义会把最后一个声明当作定义初始化为0//int a = 10;void main(){ printf("%d", a);//0 system("pause");}

多线程

单线程的局限

总共5碗饭,一个人一次一碗一碗吃。

5个人每一个人吃一碗。

一个女人10个月生一个孩子,10个女人一个月却不能生一个孩子。

多线程的局限

#include
#include
//进程#include
void run(void *p){ int *px = (int *)p;//指针转换 //printf("线程%d启动", *px); char str[100] = {0};//字符数组 sprintf(str, "线程%d启动", *px); MessageBoxA(0,str, "多线程", 0);}void main1(){ for (int i = 0; i < 5; i++) { //run(NULL); _beginthread(run, 0, &i); Sleep(10); } system("pause");}

堵塞模式与并行模式

#define  _CRT_SECURE_NO_WARNINGS//关闭安全检查#include
#include
#include
//_beginthread();_endthread();#include
//WaitForSingleObjectvoid gogogo(void *p){ int *px = (int*)p;//指针转换 //return ; //线程运行完毕以后返回 int i = 0; while (1) { if (i > 5) { printf("%d %d\n", i,*px); _endthread();//结束线程 } Sleep(1000); i++; }}void time(void *p){ int i = 0; while (1) { char str[100] = { 0 }; sprintf(str, "title 当前时间第%d秒", i); system(str); i++; Sleep(1000); }}void main(){ //time(NULL); _beginthread(time, 0, NULL); for (int i = 0; i < 5; i++) { //gogogo(NULL); HANDLE hd = _beginthread(gogogo, 0, &i);//hd是编号 //WaitForSingleObject(hd, INFINITE);//等待,堵塞模式 ,没有wait并行模式 Sleep(1000); } getchar();}

多线程实现数据的查找

#include
#include
#include
#include
int flag = 0;//意味着没有找到int * addrfind = NULL;//查找到的数据所在的地址struct MyStruct{ int *pfindstart;//要查找的首地址 int length;//限定长度。从地址開始 int num;//要查找的数据 int bh;//编号 int *pflag;//传递flag的地址,改动flag,訪问 int **addr;//传递一个指针的地址,};void find(void *p){ struct MyStruct *pstruct = (struct MyStruct *)p;//指针类型转换 //内存的遍历,从地址開始累加100个元素的大小,遍历全部元素 for (int *px = pstruct->pfindstart; px < pstruct->pfindstart + 100; px++) { Sleep(100);//0.1s 查找一次 if (*(pstruct->pflag) != 0) { printf("\n属下%d无能,其它线程已经找到", pstruct->bh); return; } if (*px == pstruct->num)//推断是否相等 { printf("\n第%d个线程找到%p,%d",pstruct->bh, px,*px);//查找 *(pstruct->pflag) = 1;//改变标识。代表找到 *(pstruct->addr) = px; return; } } printf("\n没有找到第%d个线程", pstruct->bh); return;}void main(){ int a[1000];//要查找783;数组 for (int i = 0; i < 1000; i++) { a[i] = i;//数组初始化 } struct MyStruct threaddata[10];//创建结构体数组,处理不同的线程, for (int i = 0; i < 10; i++)//创建10个线程并行查找 { //a , a+100 a+200 a+900 threaddata[i].pfindstart = a + i * 100;//计算数组的地址 threaddata[i].length = 100;//长度 threaddata[i].bh = i;//编号 threaddata[i].num = 783;//要查找的数据 threaddata[i].pflag = &flag;//标识 threaddata[i].addr = &addrfind;//存储了变量的地址 printf("\n%d\n", threaddata[i].bh);//调试输出 _beginthread(find, 0, &threaddata[i]);//线程干活 //Sleep(30);//避免同一时候訪问同一个变量,引起訪问冲突 } Sleep(30000);//避免同一时候訪问同一个变量,引起訪问冲突 system("pause"); printf("\n\n%d,%p\n\n", *addrfind, addrfind);//打印地址,还有数据 system("pause");}

|=========== 吴英强CSDN博客专栏==============|

|==  专栏文章的内容(不定期更新)===|

|==  探索linux底层的奥秘 ==========|

|==  掌握java语言的基础知识=====|

|====== 每天进步一点点,健康快乐每一天 ========|

转载地址:http://wlfqo.baihongyu.com/

你可能感兴趣的文章
Linux运维之路-安全防护OpenResty
查看>>
说说不知道的Golang中参数传递
查看>>
深入解析Vue底层实现原理
查看>>
es6之解构赋值
查看>>
如何用外部程序优化SQL语句中的IN和EXISTS
查看>>
webpack学习进阶(一)
查看>>
虚拟机硬盘vmdk压缩瘦身并挂载到VirtualBox
查看>>
详解css媒体查询
查看>>
关于浏览器缓存问题(图片更换后,页面仍优先读取缓存)
查看>>
Event Loop 其实也就这点事
查看>>
前端学习资源汇总
查看>>
ZooKeeper 文档(目录)
查看>>
Nuxt在SPA模式下的鉴权处理(1)
查看>>
函数Int3断点检测
查看>>
sqlserver 重建日志文件
查看>>
返回给定字符串中最长连续数字串
查看>>
SQL注入详解-4
查看>>
在ASP.NET MVC中对表进行通用的增删改
查看>>
实现“新手引导”效果
查看>>
SQL Server中各个系统表的作用
查看>>