top 變量值被篡改作者在實現中綴表達式轉後綴(逆波蘭表達式)的算法時,發現一個詭異現象:明明沒有對變量 top 進行賦值,其值卻在調用 isMax() 函數後發生變化。經排查,根因是數組 st[MAXSIZE] 發生越界訪問,覆蓋了緊鄰的 top 變量內存。
const MAXSIZE = 100;
int st[MAXSIZE] = {0};
int top = -1; // 棧頂指針,緊鄰 st 數組
int isMax(int n1, int n2) {
switch(n1) {
case '+': return 0;
case '-': return 0;
case '*':
case '/':
if (n2 == '+' || n2 == '-') return 1;
return 0;
default:
cout << "語法錯誤" << endl;
exit(1);
}
}
int main() {
int scr[] = {6, '*', 4, '-', 2, '+', 5, '/', 2};
const int len = 8; // 實際數組長度為 9,此處寫死 8 已埋隱患
for (int i = 0; i < len; i++) {
if (scr[i] == '+' || scr[i] == '-' || scr[i] == '*' || scr[i] == '/') {
// 關鍵缺陷:註釋掉了 top == -1 的判斷,導致首次遇到運算符時 top=-1
if (/*top == -1 ||*/ isMax(scr[i], st[top])) {
st[++top] = scr[i];
} else {
ay.num[ay.len++] = st[top--];
st[++top] = scr[i];
}
// ... 錯誤檢測代碼 ...
} else {
ay.num[ay.len++] = scr[i];
}
}
}
棧幀佈局(高地址 → 低地址): +------------------+ | 其他局部變量 | +------------------+ | top (-1) | ← 4 字節 +------------------+ | st[99] ... st[0] | ← 400 字節 +------------------+
當 top = -1 時,st[top] 實際訪問 st[-1],恰好落在 top 變量的內存位置。isMax 內部對參數 n2(即 st[-1])的讀取,實際上讀取的是 top 的值;若函數調用約定導致參數寫入棧幀,更可能直接修改 top。
top 在進入 isMax 前為 -1,返回後變為 42(運算符 '*' 的 ASCII)isMax 內打印參數地址,發現 &n2 == &toptop == -1 || 短路判斷後,問題消失-Wall -Wextra -Warray-bounds(GCC/Clang),使用 -fsanitize=address(ASan)運行期檢測std::vector/std::array(C++)或封裝帶邊界檢查的安全數組結構(C)0xDEADBEEF),定期校驗是否被篡改if (top == -1 || isMax(scr[i], st[top])) { // 短路求值保護
st[++top] = scr[i];
} else {
ay.num[ay.len++] = st[top--];
st[++top] = scr[i];
}
此外,len 應改為 sizeof(scr)/sizeof(scr[0]) 避免硬編碼錯誤。