內存模型與程序存在形式

編程思維

1,編程的時候時常想想內存大概的模型已經劃分的區域(主要四大區:靜態存儲區(數據段) 堆 棧 代碼段),[數據段可存放靜態數據和自由變量]變量 函數等在內存是在哪個區域的,加了修飾詞有什么不同;[函數代碼存放在代碼段。聲明的類如果從未使用,則在編譯時,會優化掉,其成員函數不占代碼段空間。
補充:代碼段、數據段、棧是CPU級別的邏輯概念,堆是語言級別的邏輯概念全局變量或靜態變量,放在數據段,]
[數據段:數據段(data segment)通常是指用來存放程序中已初始化的全局變量的一塊內存區域。數據段屬于靜態內存分配。]
函數形參存放位置:主函數的是放在堆里面的,臨時變量都是放在棧里面的;

2,聲明變量去"接住"你獲得的數據進行操作;實現你要的功能,不要去管其他東西;會用是一個層次,理解低層實現原理是另外一個層次;

內存主要分布:不可訪問區、代碼段、數據段、堆、棧、內核
    
①代碼段:.text:用于存放用戶代碼;.init:用于存儲系統給每一個程序自動添加的"初始化"代碼

②數據段:.bass 專門存儲未初始化的靜態變量,它們的值會被初始化為0,static int i;.data  專門存儲已初始化的靜態數據(靜態數據:所有全局變量(全局變量默認初始化為0),及static的局部變量).rodata 存放只讀數據(用const修飾),比如字符串、字符常量、整形等  char *p = "helloworld"; //"helloworld"只讀字符串

③堆:一塊自由的內存,用戶可以根據自己需求開辟空間大小,內存釋放也是由用戶自己進行釋放(malloc realloc calloc開辟堆空間,釋放free)

④棧:它是從0xC0000000往下增長的部分(后進先出),大概8M,專門存放函數局部變量(思考:如何判斷棧是往下增長的 //先進入棧的變量在棧底),
棧空間就是指放置程序的局部數據(也就是函數內數據)的內存空間;

全局變量:存放.data當中,如果沒有賦值系統默認初始化為0,如果沒有被static修飾其它文件可以調用的變量
Paste_Image.png

一 內存效率相關(常見關鍵字)

哪些區哪些特點 畫圖
①static作用(限制變量/函數(靜態)的作用域;設置變量的存儲域(主動分配內存在堆))
1.全局變量時存儲在不變區(靜態變量區)但限制作用域;不能被模塊外其它函數訪問(靜態函數類似,也可防沖突);
*靜態函數會被自動分配在一個一直使用的存儲區,直到退出應用程序實例,避免了調用函數時壓棧出棧,速度快很多;內部函數又稱靜態函數(static修飾,不怕同名)
2.修飾局部變量時變存儲區域"棧"為靜態存儲區(區別auto),代表該內存只被分配一次而且下次調用時仍維持上次的值;
例:函數中定義,static int j = 10; //此時作用等同為全局變量,靜態局部變量只初始化一次?->第二次調用不執行


static修飾.png

static總結 http://blog.csdn.net/damon_hoo/article/details/38903041

1.靜態局部變量:靜態局部變量始終存在,生存期為整個源程序,作用域和局部變量是一樣的,靜態局部變量會被自動的初始化為0.

2.靜態全局變量:靜態全局變量只能在一個文件中使用

3.靜態數據成員變量:描述整個類的特征,是整個類的成員,而不是一個對象的成員
static int i;
初始化靜態數據成員在類體外進行,而且前面不加static,以免和一般靜態變量混淆
一般在cpp里面初始化,格式
int CStudent::num = 0;

4.靜態成員函數:屬于整個類的成員函數,是整個類的成員,而不是一個對象的成員,它的調用形式可以用對象來調用它,也可以用類的名字來調用它,靜態成員函數可以有類名通過::直接調用,但是非靜態成員函數只能通過對象名來調用。
靜態成員函數沒有this指針,可以直接訪問該類的靜態成員和靜態成員函數,而不能直接操作非靜態的成員變量和非靜態成員函數,如果靜態成員函數中要引用非靜態成員,則可以通過對象來引用,

②extern 修飾的變量(這里的變量給外部使用)或者函數不僅本文使用,外部文件也可以使用?
溫工:extern引用其他文件的函數

③register 數據類型 變量名;//聲明寄存器變量
register int i; //i就是一個寄存器變量
1、用register修飾的變量告訴編譯器不要優化,運行效率高
2、不一定能100%分配變量為寄存器變量

④C中的宏與C++中的inline關鍵字聲明頻繁使用的小函數

①②對應靜態存儲期:static聲明的局部變量具有靜態存儲持續期(static storage duration),或靜態范圍(static extent).雖然他的值在函數調用之間保持有效,但是其名字的可視性仍限制在其局部域內。靜態局部對象在程序執行到該對象的聲明處時被首次初始化;
③對應自動存儲期(auto):變量在進入聲明該變量的程序塊時被建立,它在該程序塊活動時存在,退出該程序塊時撤銷

⑤synchronized
volatile三種作用:防止編譯器優化;不會阻塞線程;解決變量在多個線程之間的可見性
1.與該變量有關的運算,不要進行編譯優化,以免出錯
⑥inline內聯函數 http://www.cnblogs.com/li-hao/archive/2013/03/15/2961713.html

二 數組與指針

void型指針不能解引用(目標類型未定),解引用前必須轉化為某種具體的指針類型
④const修飾內容不能做任何改變
例子:int *const p = &test1; //保護的是p里的內容,只能在定義里賦值
//p = &test2; p為常量,不能再賦值
const char p == char const p(修改p)
(1)常量指針,不能通過這個指針改變變量的值,但是還是可以通過其他指針的引用或者變量來改變里面的值
(2)常量指針指向的值不能改變,但是這并不意味著指針不能改變,指針可以指向其它變量的
int test1 = 100;
const int p;
int pp;
p = &test1; //指針與變量關聯
pp = &test1;
test1 = 200; //通過變量改變里面的值
pp = 70; //通過其他未用const指針來修改里面的值
//
p = 25; //error: assignment of read-only location ‘
p’
printf("
p = %d\n",
p);
printf("test1 = %d\n",test1);
char *const p:
(1)指針常量:指針本身是一個常量,不能再指向別的地址
(2) 指針常量里面的地址不能改變,但是地址中保存的值是可以改變的
int test1 = 100;
int test2 = 25;
int const p = &test1; //保護的是p里的內容,只能在定義里賦值
//p = &test2; p為常量,不能再賦值
test1 =45;
p = 70;
printf("
p = %d\n",
p);
printf("test1 = %d\n",test1);
const int const p:指向常量的常指針。p里面的內容不可以改變,同時也不能通過p改變地址指向的內存

⑤數組初始化 數組求長-\n也算
bzero menset 定義剛好的數組
char buf[50]={0};//50個都為0
char buf[50]={1};//只有第一個為1

特殊定義:
void func1(void);
void func2(void (p)(void));
typedef void(
fi)(void (*f2)(void));
f1 a ;
意思:上面是一個指針(函數指針),指向返回類型為void,參數是一個函數指針的指針;

復雜函數指針.png
Paste_Image.png

long在32位編譯器下是4個字節
?引用傳參的效率

⑥typedef重命名
typedef char *p;
p a="hello";//等價于char *a="hello";

⑨inline 必須是在函數定義時修飾函數才有效,如果只是單純的在聲明時加了inline關鍵字,而在定義時未加則等于沒有適用inline關鍵字
1.使用場景:https://www.cnblogs.com/fnlingnzb-learner/p/6423917.html

//inline提高效率 函數需要短小精悍 看編譯器優化處理 編譯時替換
inline int add(int x,int y,int z){
return x + y + z;
}//類似template

三 分配優化與安全溢出

⑦泄露與溢出
堆棧溢出一般是循環的遞歸調用導致(或者大數據結構的局部變量)
⑧虛擬機溢出標志-can not write

四 內存映射函數

/*#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags,
int fd, off_t offset);
addr ----- > 我們所申請的內存空間的起始地址
NULL ----》系統自動分配
length---- >內存空間的大小
port ------>操作權限
PROT_READ 可讀
PROT_WRITE 可寫

flags------> 共享屬性
            MAP_SHARED   可以共享
            MAP_PRIVATE   私有
fd--------> 硬件設備的文件描述符
offset----》光標偏移量            

int munmap(void addr, size_t length);/

五 編譯&優化等級

http://blog.chinaunix.net/uid-25768133-id-3485479.html
attribute ((packed))告訴編譯器取消結構在編譯過程中的優化對齊,按照實際占用字節數進行對齊,是GCC特有的語法。這個功能是跟操作系統沒關系,跟編譯器有關,gcc編譯器不是緊湊模式的,我在windows下,用vc的編譯器也不是緊湊的,用tc的編譯器就是緊湊的

六 程序啟動/運行流程

1.問題:程序開機自啟(程序需要root權限才能啟動)

!/bin/bash

sh /home/hwjc/RSA/release2017-02-23/release2017-02-23/install.sh
sh /etc/init.d/mqtt.sh
ifconfig
更改 vi /etc/profile
加至末尾:echo yhn!#!%!^ | sudo -S /home/hwjc/RSA/release2017-02-23/release2017-02-23/init.sh
改完保存退出
輸入命令:source /etc/profile 即可

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容