使用指針寫入常量變量會導致運行時錯誤。系統如何知道被訪問的地址是否爲常量
const int i;
int *p;
void main()
{
p = (int*)&i;
*p = 10; // Causes runtime error
}
但在Windows系統中,一切都從RAM本身運行。
當我打印const變量和正常變量的地址時,我可以看到它們處於不同的偏移量。
系統如何知道指針訪問的地址是const
?
使用指針寫入常量變量會導致運行時錯誤。系統如何知道被訪問的地址是否爲常量
const int i;
int *p;
void main()
{
p = (int*)&i;
*p = 10; // Causes runtime error
}
但在Windows系統中,一切都從RAM本身運行。
當我打印const變量和正常變量的地址時,我可以看到它們處於不同的偏移量。
系統如何知道指針訪問的地址是const
?
嚴格來說,根據C語言標準,您的代碼會產生未定義的行爲。
實際上,鏈接器可能已將變量i
放置在可執行映像的RO部分中。
因此寫操作*p = 10
導致內存訪問衝突(又名分段錯誤)。
RO =只讀... –
RO部分是否駐留在RAM本身中? –
@AllEldhose:我在這裏的評論的其餘部分不是由C語言標準決定的,但基本上取決於底層平臺(操作系統,虛擬內存,編譯器,鏈接器等)。通常,整個可執行映像被加載到RAM中。有時它的一部分可能會被「換出」到硬盤中,以便爲其他應用程序「騰出空間」。但基本上,當它運行時 - 它是從RAM運行的(再次,取決於你的平臺 - 例如,有硬件架構可以運行所有的Flash)。 –
系統如何知道....
理想情況下,系統不需要知道。對於具有const
限定類型的對象,分配(一般情況下)將處於只讀部分,因此任何嘗試修改(寫入)都將導致訪問衝突。這是應該知道的程序員。
當我印刷
const
變量和正常變量的地址,我可以看到,他們在不同的偏移。
是的,這是有可能的,因爲正常變量駐留在讀寫內存,而const
變量將駐留在只讀存儲器中。
請注意,有沒有語法(或編譯)錯誤爲您的代碼段。只有代碼(運行時)的行爲未定義。
僅供參考,引用C11
,章§6.7.3/ P6
如果試圖通過與非常量限定左值的使用 修改與常量限定類型定義的對象類型,行爲是未定義的。 [...]
鏈接器已將全局變量'i'放置在可執行映像的RO部分中。 –
* p = 10個未定義的行爲。 – 2016-08-24 06:01:29