2012-06-26 121 views
4

Google做大量的調查研究後,我發現下面的程序讀取和寫入內存位置

#include <stdio.h> 

int main() 
{ 
    int val; 
    char *a = (char*) 0x1000; 
    *a = 20; 
    val = *a; 
    printf("%d", val); 
} 

但它拋出一個run time錯誤,在*a = 20

那麼我該如何編寫和讀取特定的內存位置?

請幫我

+0

您確定可以寫入0x1000嗎?這是什麼平臺? –

+0

@Banthar:windows中的代碼塊 –

回答

7

這是拋出一個segment violation(段錯誤),因爲它應該,因爲你不知道什麼是擺在那的地址。最有可能的是,這是內核空間,宿主環境並不想讓你無法寫入另一個應用程序的內存。你只應該寫出你知道你的程序可以訪問的內存,否則你將在運行時產生莫名其妙的崩潰。

+6

用戶代碼無法訪問內核空間(ring),這是現代操作系統,虛擬內存和MMU的基礎知識。否則你是正確的。 –

1

您可以寫入特定的內存位置。

但只有當您有權寫入該位置。

你得到的是禁止你寫入0x1000的操作系統。

+0

我在code :: blocks中運行它。它調試時出現段錯誤'SIGEGEV'錯誤 –

+0

@RasmiRanjanNayak這些信息並沒有真正改變我的答案:-) –

+0

@RasmiRanjanNayak不,它給你SIGSEGV(注意拼寫),這是POSIX術語,當程序是訪問無效的內存位置,又稱segementation故障。 – Lundin

4

如果運行在用戶空間的代碼(你是),那麼你所得到的地址是虛擬地址,而不是物理地址。你不能假設並寫入任何虛擬地址。
實際上,對於虛擬內存模型,您不能僅僅假定任何地址是有效的地址。內存管理器會將有效地址返回到編譯器實現,該實現將處理它到您的用戶程序,而不是相反。

爲了使你的程序能夠寫入到一個地址:

  1. 這應該是一個有效的虛擬地址
  2. 它不應該接觸到你的程序的地址空間
3

你不能隨便寫任何地址。您只能修改程序可以寫入的內存內容。

如果您需要修改某些變量的內容,那就是爲什麼指針是適用的。

char a = 'x'; 
char* ptr = &a; // stored at some 0x.... 
*ptr = 'b'; // you just wrote at 0x.... 
2

權限問題,操作系統將保護內存空間免受隨機訪問。

你沒有指定確切的錯誤,但我猜你是得到一個「segmentation fault」這將清楚地表明內存訪問衝突。

1

這是將數據寫入存儲單元0x1000的正確方法。但是在虛擬內存的這個時代,你幾乎永遠不會知道你想要寫入的實際內存位置,所以這種類型的東西永遠不會被使用。

如果你可以告訴我們實際問題,你正試圖解決這個問題,也許我們可以提供幫助。

+0

我得到分段錯誤錯誤 –

+0

我的意思是_why_你想寫入特定的內存地址嗎?你正在編寫的程序應該做什麼? –

+0

我在那裏參加了一個採訪,他們問我同樣的問題。這就是爲什麼 –

1

您不能隨機選擇一個內存位置並寫入。內存位置必須分配給您,並且必須是可寫的。

一般而言,您可以通過&獲得變量的參考/地址並在其上寫入數據。或者你可以使用malloc()來請求堆上的空間來寫入數據。

此答案僅涵蓋如何在內存上寫入和讀取數據。但我沒有介紹如何以正確的方式做到這一點,以便程序正常運行。其他答案可能比我的更好。

+0

我知道'malloc'會有所幫助。但是不使用'malloc'如何做? –

+0

@RasmiRanjanNayak:這取決於應用程序。但爲了僅僅寫和讀(甚至崩潰程序),您可以聲明局部變量或全局變量,然後獲取對其的引用並將數據寫入它。 – nhahtdh

+0

向下投票:我會很感激你的評論在這裏。 – nhahtdh

15

你正在做它,除了在你的系統上,你不能寫入這個內存導致分段錯誤。

分段錯誤(通常縮寫爲段錯誤),總線錯誤或訪問衝突通常是嘗試訪問CPU無法物理地址訪問的內存。它在硬件通知操作系統關於內存訪問衝突時發生。 OS內核然後發送一個信號給導致異常的進程。默認情況下,接收信號的進程轉儲核心並終止。默認的信號處理程序也可以被覆蓋以定製如何處理信號。

如果您有興趣瞭解更多查看維基百科MMU的信息,

以下是如何從堆中合法請求內存。 malloc()函數需要多個字節來分配參數。請注意,在完成使用後,每個malloc()應該與free()調用相同的內存。呼叫free()通常應與您調用malloc()時的功能相同。

#include <stdio.h> 
int main() 
{ 
    int val; 
    char *a; 

    a = (char*)malloc(sizeof(char) * 1); 

    *a = 20; 
    val = (int)*a; 
    printf("%d", val); 

    free(a); 

    return 0; 
} 

您也可以分配在棧上存儲在一個非常簡單的方法,像這樣:

#include <stdio.h> 
int main() 
{ 
    int val; 
    char *a; 
    char b; 

    a = &b; 
    *a = 20; 
    val = (int)*a; 

    printf("%d", val); 

    return 0; 
} 
+0

我可能會問,爲什麼你不只是堆棧分配一個字符,並得到它的地址?看起來過於複雜的一個簡單的例子。 –

+0

堆分配示例幾乎是必需的。這裏的目標顯然是理解正確的內存分配而不是修復一個破壞的程序。 –

-1

首先,你需要確保大約要寫入內存位置。 然後,檢查您是否有足夠的權限寫入或不寫入。