【C/C++学院】0724-堆栈简单介绍/静态区/内存完毕篇/多线程
【送给在路上的程序猿】
对于一个开发人员而言,可以胜任系统中随意一个模块的开发是其核心价值的体现。
对于一个架构师而言,掌握各种语言的优势并能够运用到系统中。由此简化系统的开发。是其架构生涯的第一步。
对于一个开发团队而言。能在短期内开发出用户惬意的软件系统是起核心竞争力的体现。
每个程序猿都不能固步自封。要多接触新的行业。新的技术领域,突破自我。
堆栈简单介绍、内存完毕篇
Const是一个伪常量
#include<stdio.h>
#include<stdlib.h>
#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<stdio.h>
#include<stdlib.h> 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<stdio.h>
#include<stdlib.h>
#include<Windows.h> //内存分配,malloc calloc,realloc
void 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<stdio.h>
#include<stdlib.h> 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<stdio.h>
#include<stdlib.h>
#include<Windows.h> 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<stdio.h>
#include<stdlib.h> //导出函数。能够载入的时候调用
_declspec(dllexport) void go()
{
//函数指针类型必须一致,否则无法调用成功
//int ** 变量名挖掉就是类型
//间接调用的方式调用函数。依据地址来调用
void(*p1)(int a) = (void(*)(int a)) 0x2c10eb;
p1(10);
void(*p2)() = (void(*)())0x2c111d;
p2();
//这里加上自己的猥琐代码,能够移花接木,唬住门外汉。
}
寄存器变量
C和汇编的混合编程
#include<stdio.h>
#include<stdlib.h> 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<stdio.h>
#include<stdlib.h>
#include<Windows.h> //导出函数。能够载入的时候调用
_declspec(dllexport) void go()
{
MessageBoxA(0, "你的360云盘存放的岛国大片被网络警察所监督", "请自首", 0);
while (1)
{
double db[1024 * 100];
}
}
栈的大小
#include<stdio.h>
#include<stdlib.h> 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<stdio.h>
#include<stdlib.h> void main()
{
int a=4;
printf("%d,%d", a, a++);//參数压栈的顺序从右向左
//5, 4
getchar();
}
#include<stdio.h>
#include<stdlib.h> void main()
{
int a=4;
printf("%d,%d", a, ++a);//參数压栈的顺序从右向左
//5, 5
getchar();
}
全局static变量,//限定仅仅有本C文件訪问
局部static变量,仅仅会初始化一次。
#include<stdio.h> 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<stdio.h>
#include<stdlib.h> //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<stdio.h>
#include<stdlib.h> 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<stdio.h>
#include<stdlib.h> int a;
int a;
int a;//未定义会把最后一个声明当作定义初始化为0
//int a = 10; void main()
{
printf("%d", a);//0 system("pause");
}
多线程
单线程的局限
总共5碗饭,一个人一次一碗一碗吃。
5个人每一个人吃一碗。
一个女人10个月生一个孩子,10个女人一个月却不能生一个孩子。
多线程的局限
#include<Windows.h>
#include<process.h>//进程
#include<stdlib.h> 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<stdio.h>
#include<stdlib.h>
#include<Windows.h>//_beginthread();_endthread();
#include<process.h>//WaitForSingleObject void 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<stdio.h>
#include<stdlib.h>
#include<process.h>
#include<Windows.h> 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");
}
【C/C++学院】0724-堆栈简单介绍/静态区/内存完毕篇/多线程的更多相关文章
- iOS开发UI篇—简单介绍静态单元格的使用
iOS开发UI篇—简单介绍静态单元格的使用 一.实现效果与说明 说明:观察上面的展示效果,可以发现整个界面是由一个tableview来展示的,上面的数据都是固定的,且几乎不会改变. 要完成上面的效果, ...
- Java提高篇—— 简单介绍Java 的内存泄漏
java最明显的一个优势就是它的内存管理机制.你只需简单创建对象,java的垃圾回收机制负责分配和释放内存.然而情况并不像想像的那么简单,因为在Java应用中经常发生内存泄漏. 本教程演示了什么是内存 ...
- Java内存分析简单介绍
原创:转载需注明原创地址 https://www.cnblogs.com/fanerwei222/p/11904422.html Java内存分析简单介绍: 1. # 设置内存溢出时自动生成堆内存快照 ...
- MPI编程简单介绍
第三章MPI编程 3.1 MPI简单介绍 多线程是一种便捷的模型,当中每一个线程都能够訪问其他线程的存储空间.因此,这样的模型仅仅能在共享存储系统之间移植.一般来讲,并行机不一定在各处理器之间共享存储 ...
- Android发展简单介绍
Android一词的本义指“机器人”,同一时候也是Google于2007年11月5日宣布的基于Linux平台的开源手机操作系统的名称,该平台由操作系统.中间件.用户界面和应用软件组成,号称是首个为移动 ...
- JAVA 文件编译执行与虚拟机(JVM)简单介绍
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytpo3 java程序的内存分配 JAVA 文件编译执行与虚拟机(JVM)介绍 ...
- 一个性能较好的jvm參数配置以及jvm的简单介绍
一个性能较好的webserverjvm參数配置: -server //服务器模式 -Xmx2g //JVM最大同意分配的堆内存,按需分配 -Xms2g //JVM初始分配的堆内存.一般和Xmx配置成一 ...
- Python常用的库简单介绍一下
Python常用的库简单介绍一下fuzzywuzzy ,字符串模糊匹配. esmre ,正则表达式的加速器. colorama 主要用来给文本添加各种颜色,并且非常简单易用. Prettytable ...
- photoshop工具使用的简单介绍
photoshop工具使用的简单介绍 我所用PhotoShop版本号是cs6,这里对其主要功能做一个简单介绍. 第一部分: 首先,ps的界面主要分为了6部分: 一.最上面的一行的菜单栏,菜单中有:文件 ...
随机推荐
- elasticsearch indices.recovery 流程分析(索引的_open操作也会触发recovery)——主分片recovery主要是从translog里恢复之前未写完的index,副分片recovery主要是从主分片copy segment和translog来进行恢复
摘自:https://www.easyice.cn/archives/231 elasticsearch indices.recovery 流程分析与速度优化 目录 [隐藏] 主分片恢复流程 副本分片 ...
- Python 字典(dict)操作(update)
1. get 注意以下两种形式的细微差别,差别在返回值的类型上: d.get(value, '') d.get(value, ['']) >> d = {} >> d.get( ...
- [ASPX] DotLiquid-Asp.net模板引擎
以前用过一段时间的PHP,感觉非常不错,其中最让我难忘的就是Smarty模板引擎,当时就微微地想Asp.net里有没有像这样的模板引擎呢?不过由于之后的工作内容都用不到,或者说没有想到用模板,这想法也 ...
- 43.qt通过qss自定义外观
样式: 文件格式类型: candy.qss /* R1 */ QDialog { /*设置背景图片*/ background-image: url(:/images/background.png); ...
- 关于Eclipse安装Scala插件不显示
关于Eclipse安装Scala插件不显示, 改变java版本仍然不能使用, 办法还是有的:下载Eclipse Scala版本 解压使用 下载在这里:http://scala-ide.org/down ...
- BigDecimal,注解
BigDecimal 问题重现 今天在干活的途中,发现一个很坑爹的问题,让我来复现下问题: 从上游接口获得的余额,对于为0的,做了判断 BigDecimal a = new BigDecimal(ac ...
- table中的td内容过长显示为固定长度,多余部分用省略号代替
如何使td标签中过长的内容只显示为这个td的width的长度,之后的便以省略号代替. 给table中必须设置属性: table-layout: fixed; 然后给 td 设置: white-spac ...
- ArrayList集合如何存储基本数据类型
ArrayList对象不能存储基本类型,只能存储引用类型的数据.类似 <int> 不能写,但是存储基本数据类型对应的包装类型是可以的. 所以,想要存储基本类型数据, <> 中的 ...
- vc++创建Win32 Application窗体过程
#include<windows.h>#include<stdio.h>LRESULT CALLBACK WinSunProc( HWND hwnd, UINT uMsg, W ...
- SLAB
slab:由于内核会有许多小对象,这些对象构造销毁十分频繁,比如i-node,dentry,这些对象如果每次构建的时候就向内存要一个页(4kb),而其实只有几个字节,这样就会非常浪费,为了解决这个问题 ...