c - gcc-8 Wstringop-截断

标签 c gcc strncpy gcc8

我正在尝试修复一些 C 代码,其中 gcc-8 提示 Wstringop-truncation(代码是 here)

在我无法控制的服务器上编译代码时,既不能添加 pragma 语句,也不能禁用 Wstringop-truncation 诊断,我收到的警告是:

gcc-8  -I"/home/hornik/tmp/R/include" -DNDEBUG -I./cqdb/include -I./crf/src -I./liblbfgs/include -I./include -I"/home/hornik/lib/R/Library/3.6/x86_64-linux-gnu/Rcpp/include" -I/usr/local/include   -fpic  -g -O2 -Wall -pedantic -mtune=native -c cqdb/src/cqdb.c -o cqdb/src/cqdb.o
cqdb/src/cqdb.c: In function ‘cqdb_writer_close’:
cqdb/src/cqdb.c:270:5: warning: ‘strncpy’ output truncated before terminating nul copying 4 bytes from a string of the same length [-Wstringop-truncation]
     strncpy((char*)header.chunkid, CHUNKID, 4);
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cqdb/src/cqdb.c: In function ‘cqdb_reader’:
cqdb/src/cqdb.c:469:9: warning: ‘strncpy’ specified bound 4 equals destination size [-Wstringop-truncation]
         strncpy((char*)db->header.chunkid, (const char*)p, 4);
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

我想重写 strncpy 语句以删除这些警告。我需要在以下几行中替换是对的吗

strncpy((char*)header.chunkid, CHUNKID, 4);
with strncpy((char*)header.chunkid, CHUNKID, 5);

and strncpy((char*)db->header.chunkid, (const char*)p, 4);
with strncpy((char*)db->header.chunkid, (const char*)p, 5);

下面是cqdb.c中的相关代码。它基本上检查文件是否为“CQDB”类型。 标记一下,虽然我真的很想访问,但我无法访问这台机器,所以我无法测试 C 代码的修复是否有效。

#define CHUNKID             "CQDB"

typedef struct {
    int8_t      chunkid[4]; /**< Chunk identifier, "CQDB". */
    uint32_t    size;       /**< Chunk size including this header. */
    uint32_t    flag;       /**< Global flags. */
    uint32_t    byteorder;  /**< Byte-order indicator. */
    uint32_t    bwd_size;   /**< Number of elements in the backward array. */
    uint32_t    bwd_offset; /**< Offset to the backward array. */
} header_t;

int cqdb_writer_close(cqdb_writer_t* dbw)
{
header_t header;
strncpy((char*)header.chunkid, CHUNKID, 4);
...
}

cqdb_t* cqdb_reader(const void *buffer, size_t size)
{
    cqdb_t* db = NULL;
    /* Check the file chunkid. */
    if (memcmp(buffer, CHUNKID, 4) != 0) {
        return NULL;
    }
    db = (cqdb_t*)calloc(1, sizeof(cqdb_t));
    const uint8_t* p = NULL;
    db->buffer = buffer;
    p = db->buffer;
    strncpy((char*)db->header.chunkid, (const char*)p, 4);
...
}

最佳答案

问题中strncpy的用法其实是正确的(左对齐缓冲区中的一些字符,右填充空字节),但是警告是因为这个函数经常被人误用试图复制以 null 结尾的字符串。

对于问题中显示的代码,我会将 strncpy 调用替换为:

set_chunkid(&header);

添加新函数的地方:

void set_chunkid(header_t *hdr)
{
    _Static_assert(sizeof CHUNKID == sizeof hdr->chunkid + 1, "chunk ID not 4 chars");

    memcpy(&hdr->chunkid, CHUNKID, sizeof hdr->chunkid);
}

如果此函数未涵盖其他用例,请更新问题。

关于c - gcc-8 Wstringop-截断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52265189/

相关文章:

c - 为什么 GCC/Clang 的清除属性不能与函数参数一起使用

c++ - C/C++ TensorFlow hello_tf.c :(. text+0xa): 未定义对 `TF_Version' 的引用

c - 以下 strncpy 调用的解释

c - 使用 strncpy() 复制 const char *

C fork 程序行为解释

c - 在C中,如何在目录中找到所有文件名并将它们存储在字符串数组中?

c - libxml2 将节点及其所有内容转换为原始 xml 字符串

c - 如何从汇编代码构建数据依赖图

c++ - 如何使用 _mm_extract_ps SSE GCC instrinc 函数将十六进制 float 转换为 C/C++ 中的 float

在 C 中从特定索引动态复制字符串