在馮.諾依曼結構CPU(如i386,ARM A8,A9)的保護模式或者哈佛結構(如8051, ARM M0,.. M3)的CPU下,C++編譯器將放置常量的內存設置為只讀模式或者放入只讀內存中,如果出現往常量內存中寫入數據就會產生訪問沖突異常。
如果在DOS的實模式的編譯器,如Turbo C/Borland C++下,可能就不會報錯。
舉例,反轉字符串:
#include "stdio.h" #include "string.h" //反轉字符串 char* ReverseStr(char* str, int len) { char* header= str; char* tail= str + len -1; char temp;//中間變量反轉字符 while(header<tail) { temp = *header; *header= *tail; *tail= temp; ++header; --tailer; } return str; } int main() { char* s = "abcde"; printf("反轉后為:%s\n",Reverse_Str(s, strlen(s))); getchar(); return 0; }
上面的程序看似沒有錯誤,
運行時
在*header=*tail; 以及 *tail=temp 行會拋出異常://xxxx.exe 中的 0xxxxxxxxx 處未處理的異常: 0xC0000005: 寫入位置 0xxxxxxxx 時發生訪問沖突
問題出在變量聲明: char *s="abcde";
這樣定義字符串變量s,s指針是保存在堆上,但字符串“abcde”是一個常量,它是保存在常量區的,被寫保護了,在反轉函數中,*header= *tail,是更改常量內存的值,被寫保護,所以會報內存寫錯誤
如果把"abcde"定義到棧或者全局變量就不存在此問題了。
char s[20];
strcpy(s, "abcde");