久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 9124|回復: 1
收起左側

局部變量內存分配解疑

[復制鏈接]
ID:3721 發表于 2015-1-5 14:23 | 顯示全部樓層 |閱讀模式
     最近在做一個疲勞試驗系統,一直在程序執行效率上做功夫。也記不清最早是從哪聽說的:定義變量,能定義在函數內絕不定義成全局,能定義在循環內絕不定義成函數范圍……深以為意!曾經犯過一個錯誤,在函數體內定義了一個和全局變量同名的變量,但在修改注釋的時候不小心將這個局部變量的生命給//掉了……編譯無錯,執行總是不對,弄了很久才發現錯誤所在。現在寫程序慎之又慎,盡量不使用全局變量,要使用也用規范的變量命名方式將全局與局部區分開。今天讀了篇文章,摘錄如下:

一個由C/C++編譯的程序占用的內存分為以下幾個部分
1、棧區(stack)— 由編譯器自動分配釋放 ,存放函數的參數值,局部變量的值等。其操作方式類似于數據結構中的棧。
2、堆區(heap) — 一般由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回收 。注意它與數據結構中的堆是兩回事,分配方式倒是類似于鏈表,呵呵。
3、全局區(靜態區)(static)—,全局變量和靜態變量的存儲是放在一塊的,初始化的全局變量和靜態變量在一塊區域, 未初始化的全局變量和未初始化的靜態變量在相鄰的另一塊區域。 - 程序結束后有系統釋放
4、文字常量區 —常量字符串就是放在這里的。 程序結束后由系統釋放
5、程序代碼區—存放函數體的二進制代碼。
一個正常的程序在內存中通常分為程序段,數據端和堆棧三部分。程序段里放著程序的機器碼和只讀數據,這個段通常是只讀,對它的寫操作是非法的。數據段放的是程序中的靜態數據。動態數據則通過堆棧來存放。在內存中,它們的位置如下:
+------------------+ 內存低端
| 程序段 |
|------------------|
| 數據段 |
|------------------|
| 堆  棧  |
+------------------+ 內存高端
堆棧是內存中的一個連續的塊。一個叫堆棧指針的寄存器(SP)指向堆棧的棧頂。堆棧的底部是一個固定地址。堆棧有一個特點就是,后進先出。也就是說,后放入的數據第一個取出。它支持兩個操作,PUSH和POP。PUSH是將數據放到棧的頂端,POP是將棧頂的數據取出。
在高級語言中,程序函數調用和函數中的臨時變量都用到堆棧。為什么呢?因為在調用一個函數時,我們需要對當前的操作進行保護,也為了函數執行后,程序可以正確的找到地方繼續執行,所以參數的傳遞和返回值也用到了堆棧。通常對局部變量的引用是通過給出它們對SP的偏移量來實現的。另外還有一個基址指針(FP,在Intel芯片中是BP),許多編譯器實際上是用它來引用本地變量和參數的。通常,參數的相對FP的偏移是正的,局部變量是負的。
當程序中發生函數調用時,計算機做如下操作:首先把參數壓入堆棧;然后保存指令寄存器(IP)中的內容,做為返回地址(RET);第三個放入堆棧的是基址寄存器(FP);然后把當前的棧指針(SP)拷貝到FP,做為新的基地址;最后為本地變量留出一定空間,把SP減去適當的數值。
在函數體中定義的變量通常是在棧上,用malloc, calloc, realloc等分配內存的函數分配得到的就是在堆上。在所有函數體外定義的是全局量,加了static修飾符后不管在哪里都存放在全局區(靜態區),在所有函數體外定義的static變量表示在該文件中有效,不能extern到別的文件用,在函數體內定義的static表示只在該函數體內有效。另外,函數中的"adgfdf"這樣的字符串存放在常量區。
……
    寫得我是心里癢癢啊……太好了!以前我有一個錯誤認識,示例:
void    aaa()
{
    int i;
    for ( i = 0; i < 100; ++ i )
    {
        int j;
        j = i;
    }
}

我總以為調用函數時 i 聲明并分配內存一次,而 j 每循環一次分配一次內存。恐怕是和變量作用域混淆了。以前寫程序不用太過關心效率,聲明在循環里還是循環外都不以為意,執行起來也無甚差別。可現在,循環次數更加巨大,還要求在極短時間內執行完畢……我有點慌咯,我的局部變量假如還不是系統變量類型而是我自己聲明的類……那光構造和析構都要人老命了……我到底是不是庸人自擾呢?
寫程序試試吧……
.h
class TForm1
{
public:  
    void    aaa();
};

.cpp
void    TForm1::aaa()
{
    int i = 0;
    for ( i; i < 100; ++ i )
    {
        int j;
        j = i;
    }
}

主函數省略,也就是調用aaa()。然后第一次主動打開CPU觀察器……居然是第一次,寫了快4年程序的第一次!我想被人知道我得被鄙視個半死……幸好以前8086匯編學得還行,單片機也一直堅持用匯編編程,有這些基礎,看起來也不是很難:


感謝上面說的那篇“神作”!可愛的 add esp,-0x08 原來一早就分配好區域了……[ ebp-0x04 ]就是i,[ ebp-0x08 ]就是j。感謝偉大的編譯器幫我們干完這些……看來我是杞人憂天了。

以前一直以為變量的內存分配就是“new”一塊內存……大錯特錯啊……棧區就擺在那,局部變量若直接聲明,分配個P內存。但也由于棧區大小有限制,所以終于明白了一句話:優先用vector管理數組,堆是不限制咱的,vector本身就是幾個指針而已。于是又明白了一點……以前在函數內建一個超大數組編譯出錯,不是內存不夠,是棧區限制,以前還以為這是數組本身的特性所致。
    以前夜郎自大了……還是虛心學習吧……

回復

使用道具 舉報

ID:79197 發表于 2015-5-8 11:02 | 顯示全部樓層
好貼,mark一下,以后繼續學習
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 成人美女免费网站视频 | 久久久久久国产精品免费免费男同 | 一区二区高清 | 亚洲欧美日韩高清 | 精品一区二区久久久久久久网站 | 97国产精品视频人人做人人爱 | 夜夜摸夜夜操 | 91精品国产乱码久久久久久久 | 99精品欧美一区二区三区 | 欧美激情综合五月色丁香小说 | 色综合一区二区 | 国产精品高潮呻吟久久aⅴ码 | 一级网站 | 天天干夜夜操视频 | 中文亚洲字幕 | 中文字幕日韩欧美 | 国产精品久久久久久久久免费高清 | 亚洲天堂久久 | 国产成年人小视频 | 视频二区| 国产成人久久精品一区二区三区 | 美女爽到呻吟久久久久 | 7777精品伊人久久精品影视 | 新91| 成人在线视频看看 | 亚洲视频在线看 | 国产9999精品 | 成人深夜福利 | 日韩在线中文字幕 | a在线免费观看视频 | 亚洲黄色一级 | 韩日在线视频 | 成人欧美日韩一区二区三区 | 亚洲综合在线视频 | 日韩在线免费 | 久久精品国产亚洲夜色av网站 | 精品久久久久久久久久久 | 国产美女在线观看 | 国产日韩一区二区 | 日韩欧美三级 | 国产精品国产三级国产aⅴ无密码 |