Re: [問題] 為什麼兩個 pointer 不能轉 const

看板C_and_CPP作者時間10年前發表 (2015/02/08 15:03), 10年前編輯推噓5(5029)
留言34則, 4人參與, 最新討論串3/4 (看更多)
來段程式好了 這個問題要分成內建type和自定義class 這兩個會有不同的結果 由於要讓違法的語法compile過,所以加上-fpermissive這個flag <狀況一: 自定義class> class aaa { public: void modify(int s){i=s;} void print()const{cout<<i<<endl;} private: int i=1; }; int main() { aaa const** aq; //老大 aaa* ap; //老二 const aaa ax; //老三 aq = &ap; //這是被禁止的,但是加上-fpermissive暫時編譯過 *aq = &ax; //由於*aq=ap,所以ap指向ax ap->modify(5566); //ax.i變成5566 !!! 執行期沒有掛 ax.print(); } <狀況二: 內建type> int const** q; int* p; const int x=1; q = &p; *q = &x; *p=5566; //x還是1並沒變5566,執行期沒有掛 <結論> 1.基於安全考量所以int **不能轉成int const ** (可以參考上篇po文) 2.自定義class的const物件用走漏洞的方式可以更改 3.內建type的const變數用走漏洞的方式改不動,我不知道為什麼,有請高手解釋 4.執行期都不會掛,執行期應該不會去檢查,這會影響效率 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 114.25.240.10 ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1423407806.A.ADF.html ※ 編輯: RealJack (114.25.240.10), 02/08/2015 23:05:09 ※ 編輯: RealJack (114.25.240.10), 02/08/2015 23:08:27

02/09 00:08, , 1F
我有在 Windows 用 g++ 編譯試過,const int 剛好被放在
02/09 00:08, 1F

02/09 00:09, , 2F
唯讀記憶體,所以有碰過改完 Runtime 當掉的狀況。
02/09 00:09, 2F

02/09 00:10, , 3F
至於 x 還是 1 沒變 5566,那是編譯器在編譯時,就直接
02/09 00:10, 3F

02/09 00:10, , 4F
把值寫死成 1,他不會在 Runtime 重新讀取 x 的內容
02/09 00:10, 4F

02/09 15:04, , 5F
我覺得還是有點問題,編譯會直接寫死應該只有巨集之類才
02/09 15:04, 5F

02/09 15:05, , 6F
@RealJack 世界上有個技術叫最佳化
02/09 15:05, 6F

02/09 15:06, , 7F
會發生,我把const全部去掉後發現內建type的值會改變
02/09 15:06, 7F

02/09 15:07, , 8F
然後用objdump比較這兩個.o檔,發現組語都一樣
02/09 15:07, 8F

02/09 15:07, , 9F
02/09 15:07, 9F

02/09 15:08, , 10F
這樣要如何解釋加const和沒有const的行為會不一樣呢?
02/09 15:08, 10F

02/09 15:36, , 11F
其實改了,只是之後用到符號x的時候極可能會直接置換成常數1
02/09 15:36, 11F

02/09 15:37, , 12F
改成int y=1;const int x=y;或volatile const int x=1;
02/09 15:37, 12F

02/09 15:38, , 13F
就會看出一樓說的差別,因為會強制使用可讀寫位址存放x
02/09 15:38, 13F

02/09 15:38, , 14F
編譯器也不會把符號x置換成常數1
02/09 15:38, 14F

02/09 15:42, , 15F
@RJ 你把x丟入函式(例如printf)再看組語就知道
02/09 15:42, 15F

02/09 15:43, , 16F
丟x和丟*p是不同結果,因為x可能會直接被置換成常數
02/09 15:43, 16F

02/09 15:55, , 17F
const這個字在執行期沒有意義,執行後只看memory protection
02/09 15:55, 17F

02/09 15:56, , 18F
本質上不是效率考量,精確說是根本不考量
02/09 15:56, 18F

02/09 18:12, , 19F
02/09 18:12, 19F

02/09 18:24, , 20F
我先研究一下好了...背後有很多些東西要釐清@@
02/09 18:24, 20F

02/09 18:25, , 21F
再請教一下要如何確定變數被放在唯讀的記憶體區塊,感謝!
02/09 18:25, 21F

02/09 18:30, , 22F
我下中斷點看到 x 的
02/09 18:30, 22F

02/09 18:30, , 23F
位址後,這個 debugger 有提供記憶體分佈資訊,其中的
02/09 18:30, 23F

02/09 18:31, , 24F
00409000 起始位址這項目,它的存取欄位只有寫 R 就唯讀
02/09 18:31, 24F

02/10 09:53, , 25F
通常要確定就是用debugger去看編譯後結果,像樓上的反組譯
02/10 09:53, 25F

02/10 09:55, , 26F
顯示x存在0x409050,p則是用堆疊esp+1c的位址;然後現在os基
02/10 09:55, 26F

02/10 10:07, , 27F
本上除了堆疊和堆積幾乎都是唯讀,也可以用debugger查詢
02/10 10:07, 27F

02/10 10:09, , 28F
怎麼配是編譯器的決定,不過字面常數或全域const容易配唯讀
02/10 10:09, 28F

02/10 10:16, , 29F
應該說怎麼配是編譯器的初稿,os的定案;編譯器決定位置,os可
02/10 10:16, 29F

02/10 10:17, , 30F
決定rwx讀寫執行權限,也可能修改區塊基底位址(ASLR)
02/10 10:17, 30F

02/10 10:25, , 31F
(這裡說的編譯器指的是同時有編譯,組譯,連結功能的程式)
02/10 10:25, 31F

02/10 10:40, , 32F
有點想說通常寫程式不用去探究這些;今天就是因為某種程度
02/10 10:40, 32F

02/10 10:41, , 33F
而言欺騙了編譯器(先告訴它const而後又要去改),既然越過了
02/10 10:41, 33F

02/10 10:42, , 34F
編譯器,就需要更底層的資訊來解釋發生的現象
02/10 10:42, 34F
文章代碼(AID): #1Krtg-hV (C_and_CPP)
文章代碼(AID): #1Krtg-hV (C_and_CPP)