簡體   English   中英

是否應該生成gcc警告?

[英]Should this generate a gcc warning?

K&R C(第二版,第5.5節)指出以下內容(我強調):

char amessage[] = "a message"; /* an array */
char *pmessage = amessage; /* a pointer */

amessage是一個大到足以容納字符序列的數組,'\\ 0'用於初始化它。 可以更改陣列中的單個字符,但是消息將始終引用相同的存儲 OTOH, pmessage是一個指針,初始化為指向一個字符串常量; 隨后可以修改指針以指向別處; 但是如果您嘗試修改字符串內容,則結果是不確定的

現在,我的問題是,在使用-Wall編譯以下程序時,Linux機器上的gcc 4.6.1(或c99)是否應生成警告:

int main(void) {
  char amessage[] = "a message";
  char *pmessage = "a message";
  pmessage[0] = 'b';
  return 0;
}

(我發現gcc不會產生任何警告。如果我正確解釋上述內容,我的期望是它應該。)

盡管您對K&R的引用是正確的,但我不希望這段代碼會產生警告,因為在一般情況下很難跟蹤此類錯誤。

例如,考慮一段代碼,其中的指針最初指向一個可修改的內存塊,然后您對其進行一些操作,然后將其分配為指向字符串文字:

char [] ok = "quick brown fox";
char *ptr = ok;
for (int i = 0 ; i != 5 ; i++) {
    *ptr++ = '-'; // OK
}
ptr = "jumps over the lazy dog";
ptr[0] = 'J'; // Bad

對於編譯器,跟蹤這些分配並發出警告非常棘手。 不可能涵蓋所有情況,因為指向字符串文字的指針可能來自外部鏈接函數。

僅僅因為代碼錯誤並不意味着gcc可以為其生成警告。 如果在編譯時可以檢測到所有未定義行為的實例,則沒有理由將該行為保留為未定義。 它可能只是一個強制性錯誤,或編譯為等效的abort(); 或類似的。

我同意gcc在這種情況下生成警告很容易。 但是關於:

int main(void) {
  char amessage[] = "a message";
  char *pmessage = "a message";
  if (is_prime(some_constant_with_100_million_digits))
      pmessage = amessage;
  pmessage[0] = 'b';
  return 0;
}

它會調用UB嗎?

它可能沒有警告,因為它是未定義的。

同樣我可以這樣做:

char amessage[] = "a message";
char *pmessage = amessage;
free(pmessage);

它沒有警告,但應該是段錯誤。

我認為警告是針對已定義的行為。

好吧,因為pmessage不是指向const的指針,所以不希望說什么,在這種情況下,因為它沒有進行足夠的靜態分析(您可以嘗試使用-O開關進行查看)如果這帶來了更多的洞察力,或者因為在這種情況下沒有人讓它說出任何東西 - 這通常意味着沒有機會從未定義的行為中做出不直觀的優化。

GCC支持-Wwrite-strings ,這將在初始化時引發問題,迫使您將pmessage指針指向const,隨后使以下行變為非法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM