【发布时间】:2020-12-03 13:48:05
【问题描述】:
我收到gcc -std=gnu17 -Wall -Werror -Wshadow -O3 test.c 的警告:
In function ‘insertString’,
inlined from ‘replaceString’ at test.c:94:5,
inlined from ‘main’ at test.c:110:22:
test.c:69:5: error: ‘strncat’ output may be truncated copying between 0 and 77 bytes from a string of length 80 [-Werror=stringop-truncation]
strncat(source, buffer, STRING_SIZE - 1 - position - strlen(stringToInsert));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
从main() 中删除do while 循环(不对相关的strncat() 语句进行任何更改)会使警告消失。
- 警告是什么意思,为什么会消失?
- 我应该在代码中加入哪些更改以使上述 gcc 命令不会触发警告? 解决方案不能简单地禁用警告(使用 fe.#pragma 语句)。 解决方案必须使用 strncat() 函数。
不重要:这是出于学习目的,请进行描述。该程序解决了 Stephen G. Kochan 的“Programming in C (4th Edition)”一书第 9 章的练习 9。
代码:
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#define STRING_SIZE 81
int findString(const char strToSearch[], const char strSought[])
{
int strToSearchLength = strlen(strToSearch);
int strSoughtLength = strlen(strSought);
for (int i = 0; i <= strToSearchLength - 1; ++i)
{
if (strToSearch[i] == strSought[0])
{
int j = 0;
while (strToSearch[i+j] == strSought[j])
{
if (strSought[j+1] == '\0')
{
return i;
}
++j;
}
}
else if (i > strToSearchLength - strSoughtLength - 1)
{
return -1;
}
}
return -1;
}
bool removeString(char source[], const int start, const int nCharsToRemove)
{
int i, sourceLength = strlen(source);
if (start + nCharsToRemove > sourceLength || start < 0 || nCharsToRemove < 0)
{
printf("Error in function removeString(): invalid parameters.\n");
return false;
}
else
{
for (i = start; i < sourceLength; ++i)
{
source[i] = source[i + nCharsToRemove];
}
source[i] = '\0';
return true;
}
}
void insertString(char source[], const char stringToInsert[], const int position)
{
char buffer[STRING_SIZE];
int i = 0;
while (source[position + i] != '\0' && position + i < STRING_SIZE - 1)
{
buffer[i] = source[position + i];
++i;
}
buffer[i] = '\0';
source[position] = '\0';
strncat(source, stringToInsert, STRING_SIZE - 1 - position);
// THE STATEMENT MENTIONED IN THE WARNING:
strncat(source, buffer, STRING_SIZE - 1 - position - strlen(stringToInsert));
}
/* A function to replace the first occurence of the string s1
* inside the source string, if it exists, with the string s2
*/
bool replaceString(char source[], const char s1[], const char s2[])
{
int findString(const char strToSearch[], const char strSought[]);
bool removeString(char source[], const int start, const int nCharsToRemove);
void insertString(char source[], const char stringToInsert[], const int position);
int s1_position;
bool success;
// locate s1 inside source
s1_position = findString(source, s1);
if (s1_position == -1)
return false;
// remove s1 from source
success = removeString(source, s1_position, strlen(s1));
if (! success)
return false;
// insert s2 into source at the proper location
insertString(source, s2, s1_position);
return true;
}
int main(void)
{
char text[STRING_SIZE] = "1 is first*";
// uncommenting the following comment and discarding what follows it makes the warning go away
/*
replaceString(text, "is", "one");
printf("%s\n", text);
*/
bool stillFound;
do
stillFound = replaceString(text, "is", "one");
while (stillFound);
printf("%s\n", text);
return 0;
}
【问题讨论】:
-
如果知道缓冲区太小在编译时然后使用更大的缓冲区。
-
The solution has to use strncat() function.?为什么?strlcat呢?你抄了书里面的东西吗?The code:这是一个例子,但肯定不是minimal。 minimal reproducible example 可能会更短,不是吗?。 -
这能回答你的问题吗? stackoverflow.com/questions/50198319/…
-
@KamilCuk 您发布的链接没有解释错误的含义,触发它的原因,为什么删除
do while循环使其消失以及如何解决问题(如果有的话)。 -
@KamilCuk 使用另一个函数可以绕过这个问题。警告是有原因的,我认为真正了解正在发生的事情是件好事。这是我的代码。我可以看到如何通过用常量替换一些函数来缩短它,但我不知道如何使问题更容易看到,如果您不同意,您有什么建议吗?
标签: c gcc compiler-warnings truncation