在Google
做大量的調查研究後,我發現下面的程序讀取和寫入內存位置
#include <stdio.h>
int main()
{
int val;
char *a = (char*) 0x1000;
*a = 20;
val = *a;
printf("%d", val);
}
但它拋出一個run time
錯誤,在*a = 20
。
那麼我該如何編寫和讀取特定的內存位置?
請幫我
在Google
做大量的調查研究後,我發現下面的程序讀取和寫入內存位置
#include <stdio.h>
int main()
{
int val;
char *a = (char*) 0x1000;
*a = 20;
val = *a;
printf("%d", val);
}
但它拋出一個run time
錯誤,在*a = 20
。
那麼我該如何編寫和讀取特定的內存位置?
請幫我
這是拋出一個segment violation(段錯誤),因爲它應該,因爲你不知道什麼是擺在那的地址。最有可能的是,這是內核空間,宿主環境並不想讓你無法寫入另一個應用程序的內存。你只應該寫出你知道你的程序可以訪問的內存,否則你將在運行時產生莫名其妙的崩潰。
用戶代碼無法訪問內核空間(ring),這是現代操作系統,虛擬內存和MMU的基礎知識。否則你是正確的。 –
您可以寫入特定的內存位置。
但只有當您有權寫入該位置。
你得到的是禁止你寫入0x1000
的操作系統。
我在code :: blocks中運行它。它調試時出現段錯誤'SIGEGEV'錯誤 –
@RasmiRanjanNayak這些信息並沒有真正改變我的答案:-) –
@RasmiRanjanNayak不,它給你SIGSEGV(注意拼寫),這是POSIX術語,當程序是訪問無效的內存位置,又稱segementation故障。 – Lundin
如果運行在用戶空間的代碼(你是),那麼你所得到的地址是虛擬地址,而不是物理地址。你不能假設並寫入任何虛擬地址。
實際上,對於虛擬內存模型,您不能僅僅假定任何地址是有效的地址。內存管理器會將有效地址返回到編譯器實現,該實現將處理它到您的用戶程序,而不是相反。
爲了使你的程序能夠寫入到一個地址:
你不能隨便寫任何地址。您只能修改程序可以寫入的內存內容。
如果您需要修改某些變量的內容,那就是爲什麼指針是適用的。
char a = 'x';
char* ptr = &a; // stored at some 0x....
*ptr = 'b'; // you just wrote at 0x....
權限問題,操作系統將保護內存空間免受隨機訪問。
你沒有指定確切的錯誤,但我猜你是得到一個「segmentation fault
」這將清楚地表明內存訪問衝突。
這是將數據寫入存儲單元0x1000的正確方法。但是在虛擬內存的這個時代,你幾乎永遠不會知道你想要寫入的實際內存位置,所以這種類型的東西永遠不會被使用。
如果你可以告訴我們實際問題,你正試圖解決這個問題,也許我們可以提供幫助。
我得到分段錯誤錯誤 –
我的意思是_why_你想寫入特定的內存地址嗎?你正在編寫的程序應該做什麼? –
我在那裏參加了一個採訪,他們問我同樣的問題。這就是爲什麼 –
您不能隨機選擇一個內存位置並寫入。內存位置必須分配給您,並且必須是可寫的。
一般而言,您可以通過&
獲得變量的參考/地址並在其上寫入數據。或者你可以使用malloc()來請求堆上的空間來寫入數據。
此答案僅涵蓋如何在內存上寫入和讀取數據。但我沒有介紹如何以正確的方式做到這一點,以便程序正常運行。其他答案可能比我的更好。
你正在做它,除了在你的系統上,你不能寫入這個內存導致分段錯誤。
分段錯誤(通常縮寫爲段錯誤),總線錯誤或訪問衝突通常是嘗試訪問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;
}
我可能會問,爲什麼你不只是堆棧分配一個字符,並得到它的地址?看起來過於複雜的一個簡單的例子。 –
堆分配示例幾乎是必需的。這裏的目標顯然是理解正確的內存分配而不是修復一個破壞的程序。 –
首先,你需要確保大約要寫入內存位置。 然後,檢查您是否有足夠的權限寫入或不寫入。
您確定可以寫入0x1000嗎?這是什麼平臺? –
@Banthar:windows中的代碼塊 –