Lint:调用函数'memcpy(void *,const void *,std :: size_t)'违反语义'(3n> 4)'

时间:2014-02-11 09:25:56

标签: c++ lint

这是我的代码库的一部分。 我没有得到警告的意思,所以我无法解决这个问题...... 代码:

struct ParamsTube{
    uint8                Colours01[4];
    uint8                Colours02[4];
    uint8                Colours03[4];
};

void sample_fun(const uint8 *diagData){
    ParamsTube Record;
    memcpy(&Record.Colours01[0], &diagData[0], 4); //Line 1
    memcpy(&Record.Colours02[0], &diagData[4], 4); //Line 2
    memcpy(&Record.Colours03[0], &diagData[8], 4); //Line 3
}

和第1,2和3行的逻辑LINT警告426是

Call to function 'memcpy(void *, const void *, std::size_t)' violates semantic '(3n>4)'

你能告诉我它究竟意味着什么......

2 个答案:

答案 0 :(得分:7)

(3n > 4)表示用于调用memcpy()的第三个参数应大于4,并且您的调用违反了此语义。语义似乎表明memcpy()不应该用于复制小于机器字的数据(通常为4)。这就是lint警告你的原因。语义是否合适是另一个问题。


以下是棉绒警告426的解释:

  

426调用函数'Symbol'违反语义'String' - 当违反用户语义(由-sem定义)时发出此警告消息。 'String'是被违反的语义的子部分。例如:

//lint -sem( f, 1n > 10 && 2n > 10 )  
        void f( int, int );  
        ...  
        f( 2, 20 );  

结果显示消息:

Call to function 'f(int, int)' violates semantic '(1n>10)'

因此,您环境中的memcpy()可能具有这样的前导lint语义:

// lint -sem(memcpy, 3n > 4)
void* memcpy(void* s1, const void* s2, std::size_t n);

对于您的情况,如果您想要实现的目标是:

memcpy(&Record.Colours01[0], &diagData[0], 4); //Line 1
memcpy(&Record.Colours02[1], &diagData[4], 4); //Line 2
memcpy(&Record.Colours03[2], &diagData[8], 4); //Line 3

然后简单地说:

memcpy(&Record, diagData, sizeof(Record));  

将在不触发lint警告的情况下完成所有工作。

答案 1 :(得分:1)

Lint告诉您不应该将memcpy调用4个或更少的字节。

这是愚蠢的。

现代编译器知道它是什么memcpy。如果使用GCC或Clang上的优化进行编译,至少可以在x86上找到,在生成的代码中,4字节memcpy已被单个mov替换。 (好吧,从内存复制到内存时可能有两个mov。)

编写此代码的方式是唯一一种可靠,安全的方法来编写它,而不是逐个编写字节副本。特别是,编写此代码不可移植:

*((uint32_t*)&Record.Colours01[0]) = *((uint32_t*)&diagData[0]);

这将适用于x86,但仅限于该平台允许未对齐的访问。但是如果diagData[0]没有与4字节边界对齐(并且绝对没有理由认为它是这样),那么这是一个未对齐的访问,并且很可能在其他平台上触发陷阱(ARM具有对齐 - 检查模式; IA-64和已故的Alpha根本不支持未对齐访问,各种嵌入式芯片也是如此。

就此而言,你甚至不能假设Colours01是一致的。编译器应该对齐它没有任何约束理由;堆栈上的其他变量可能会使其不对齐。

memcpy无论对齐是什么都是安全的,同时让编译器有机会将其优化为它认为最有效的任何内容(例如x86上的mov,其中未对齐的访问是安全的,并且可能仍然比替代方案快。)

Lint抱怨这是对Lint的作者或memcpy上的注释的严重错误。无论哪种方式,你都不应该遵循这条规则;它导致更糟糕的代码。