首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C 語言字符串字面量不可修改:指針指向常量區導致運行崩潰

     編輯:程式設計綜合問答

崩潰代碼


char *ptr = " asd as,vs aw"; // 指向只讀數據段
delspace(ptr);               // 嘗試修改內容 → 段錯誤/SIGSEGV

void delspace(char *ps) {
    char *pt = ps;
    while (*ps) {
        if (*ps != ' ') *pt++ = *ps; // 寫入只讀內存
        ps++;
    }
    *pt = '\0';
}

根因

char *ptr = "literal" 使 ptr 指向**只讀數據段**(.rodata),任何修改嘗試觸發硬件保護異常。編譯器不報錯是歷史兼容性妥協(C89 允許),但 C++11 已棄用,現代編譯器會警告。

修復方案

1. 使用數組初始化(棧上可修改副本)


char ptr[] = " asd as,vs aw"; // 編譯器在棧上分配數組並拷貝字面量
delspace(ptr); // 安全修改

2. 動態分配副本


char *ptr = strdup(" asd as,vs aw"); // malloc + strcpy
delspace(ptr);
free(ptr); // 記得釋放

3. const 正確性(防患未然)


const char *ptr = " asd as,vs aw"; // 編譯期禁止修改
// delspace(ptr); // 編譯錯誤:丟棄 const 資格
// 需修改函數簽名:
void delspace(const char *src, char *dest); // 輸出到目標緩衝區

內存模型圖解


char *p1 = "hello";  // p1 ──────► [.rodata] "hello\0" (只讀)
char p2[] = "hello"; // p2 ──────► [.stack]  "hello\0" (可讀寫)
char *p3 = malloc(6); strcpy(p3, "hello"); // p3 ──► [.heap]  "hello\0" (可讀寫)

最佳實踐清單

  1. 字面量賦值必加 const:const char *s = "..."
  2. 需修改時用數組:char s[] = "..."
  3. 函數參數不修改加 const:void f(const char *p)
  4. 開啟編譯器警告:-Wwrite-strings (GCC/Clang) / /W4 (MSVC)

**一字之差**:*ptr vs ptr[],決定運行時崩潰與正常運行的分水嶺。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved