![](/img/trans.png)
[英]Why does gcc -Wdiscarded-qualifiers complain about this code?
[英]Why does GCC 9.1.0 sometimes complain about this use of strncpy()?
這是一個40行的MCVE( 最小,完整,可驗證的例子 ) - 或接近最小的東西 - 從最初包含32個標題的1675行源文件中減少(其中大多數包括多個其他標題 - 用gcc -H
編譯它gcc -H
列出了來自項目和系統的464個頭文件,其中許多都是多次。 該文件是先前在沒有警告的情況下編譯的工作代碼(GCC 8.3.0),但不是GCC 9.1.0。 所有結構,功能,類型,變量名稱都已更改。
pf31.c
#include <string.h>
enum { SERVERNAME_LEN = 128 };
typedef struct ServerQueue
{
char server_name[SERVERNAME_LEN + 1];
struct ServerQueue *next;
} ServerQueue;
extern int function_under_test(char *servername);
#ifdef SUPPRESS_BUG
extern int function_using_name(char *name);
#endif /* SUPPRESS_BUG */
extern int GetServerQueue(const char *servername, ServerQueue *queue);
int
function_under_test(char *servername)
{
ServerQueue queue;
char name[SERVERNAME_LEN + 1];
if (GetServerQueue(servername, &queue) != 0)
return -1;
char *name_in_queue = queue.server_name;
if (name_in_queue)
strncpy(name, name_in_queue, SERVERNAME_LEN);
else
strncpy(name, servername, SERVERNAME_LEN);
name[SERVERNAME_LEN] = '\0';
#ifdef SUPPRESS_BUG
return function_using_name(name);
#else
return 0;
#endif /* SUPPRESS_BUG */
}
當使用GCC 9.1.0編譯時(在運行macOS 10.14.5 Mojave的Mac上,或運行RedHat 5.x的Linux VM上 - 請不要問!),使用選項-DSUPPRESS_BUG
我沒有錯誤,但是有選項-USUPPRESS_BUG
,我收到一個錯誤:
$ gcc -std=c11 -O3 -g -Wall -Wextra -Werror -DSUPPRESS_BUG -c pf31.c
$ gcc -std=c11 -O3 -g -Wall -Wextra -Werror -USUPPRESS_BUG -c pf31.c
In file included from /usr/include/string.h:417,
from pf31.c:1:
pf31.c: In function ‘function_under_test’:
pf31.c:30:9: error: ‘__builtin_strncpy’ output may be truncated copying 128 bytes from a string of length 128 [-Werror=stringop-truncation]
30 | strncpy(name, name_in_queue, SERVERNAME_LEN);
| ^~~~~~~
cc1: all warnings being treated as errors
$
當我使用GCC 8.3.0編譯時,我沒有報告錯誤。
一個問題的兩個方面:
-USUPPRESS_BUG
編譯代碼時會抱怨使用strncpy()
? -DSUPPRESS_BUG
編譯代碼時為什么不抱怨?
strncpy()
來限制復制的數據量,這是它為”設計的“。 我有另一個非錯誤的變體,改變了function_under_test()
的簽名 - 這里是一組差異:
11c11
< extern int function_under_test(char *servername);
---
> extern int function_under_test(char *servername, ServerQueue *queue);
20c20
< function_under_test(char *servername)
---
> function_under_test(char *servername, ServerQueue *queue)
22d21
< ServerQueue queue;
25c24
< if (GetServerQueue(servername, &queue) != 0)
---
> if (GetServerQueue(servername, queue) != 0)
27c26
< char *name_in_queue = queue.server_name;
---
> char *name_in_queue = queue->server_name;
無論是否定義了SUPPRESS_BUG
它都會干凈地編譯。
正如您可以從SUPPRESS_BUG
術語中猜到的那樣,我傾向於認為這是GCC中的錯誤,但我對於宣稱它只是一個而言我有點謹慎。
更多關於原始代碼:功能本身長540線; strncpy()
塊在函數中出現約170行; 對應於name
的變量在函數中進一步使用了多個函數調用,其中一些函數調用name
作為參數並為函數提供返回值。 這更符合-DSUPPRESS_BUG
代碼,除了在“實際代碼”中,錯誤不會被抑制。
在GCC 9.0中發現了幾個與strncpy
相關的編譯警告,並在此處和此處進行了報告。
其中一個是問題中提到的錯誤,似乎發生在文件string_fortified.h
:
/usr/include/bits/string_fortified.h:106:10: warning: ‘__builtin_strncpy’ output may be truncated copying 16 bytes from a string of length 16 [-Wstringop-truncation]
106 | return __builtin___strncpy_chk (__dest, __src, __len, __bos (__dest));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
對此的回應是在2019年4月15日給出的:
感謝您的報告,但GCC 9仍處於開發階段。 我們在當前穩定的GCC 7.4或GCC 8.3中沒有看到上述錯誤。 我們感謝先前的通知,並接受PR來解決GCC 9的問題,但是現在我們的目標編譯器是gcc stable。
所以我認為錯誤可能是版本9和9.1不穩定版本的結果。 希望在這些版本穩定后它們將被淘汰。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.