3

所以有这个 gcc 警告让我感到困扰:

warning: assuming signed overflow does not occur when simplifying multiplication

它指向的代码如下所示:

/* Move the memory block of entries after the removed one - if any. */          
if (database->entries + database->entries_size - 1 != database_entry) {         
    memmove(                                                                    
        database_entry,                                                         
        database_entry + 1,                                                     
        sizeof(spm_database_entry_t)                                            
            * (                                                                 
                (database->entries + database->entries_size)                    
                - database_entry - 1                                            
            )                                                                   
    );                                                                          
}

您可以很容易地猜到,它会在元素移除后移动容器的部分内存,以允许其进一步重新分配(缩小)。

  • database_entry是指向spm_database_entry_t*已移除元素的类型指针
  • database->entries是指向数组的指针spm_database_entry_t
  • database->entries_size是移除size_t的代表数字database->entries元素

如何摆脱警告?我可以防止乘法简化还是有更好的方法来计算需要移动多少内存?

编辑

你确定database_entry < database->entries + database->entries_size吗?

积极的。

您使用的编译器标志是什么?

-Wall -Wextra -Wshadow -Wpointer-arith -Wcast-qual -Wstrict-prototypes
-Wmissing-prototypes -Wdeclaration-after-statement -Wwrite-strings
-Winit-self -Wcast-align -Wstrict-aliasing=2 -Wformat=2
-Wmissing-declarations -Wmissing-include-dirs -Wno-unused-parameter
-Wuninitialized -Wold-style-definition -Wno-missing-braces
-Wno-missing-field-initializers -Wswitch-default -Wswitch-enum
-Wbad-function-cast -Wstrict-overflow=5 -Winline -Wundef -Wnested-externs
-Wunreachable-code -Wfloat-equal -Wredundant-decls
-pedantic -ansi
-fno-omit-frame-pointer -ffloat-store -fno-common -fstrict-aliasing 

编辑2

在乘法unsigned int之前强制转换似乎可以解决问题,但强制转换size_t不会。我不明白-标准说size_t总是未签名...

编辑3

如果上下文可以有任何用途:https ://github.com/msiedlarek/libspm/blob/master/libspm/database.c#L116

编辑4

基于史蒂夫哈的回答的解决方案:

/* Calculate how meny entries need moving after the removal. */                 
size_t entries_to_move = (                                                             
    (database->entries + database->entries_size)                                
    - database_entry - 1                                                        
);                                                                              

/* Move the memory block of entries after the removed one - if any. */          
memmove(                                                                        
    database_entry,                                                             
    database_entry + 1,                                                         
    sizeof(spm_database_entry_t) * entries_to_move                              
);
4

2 回答 2

1

就个人而言,我更喜欢额外的中间临时变量。编译器将看到它们仅用于一次计算,并将优化变量;但是在调试版本中,您可以单步执行,检查变量,并确保它确实按照您的预期进行。

/* Move the memory block of entries after the removed one - if any. */          
assert(database_entry >= database->entries &&
        database_entry < database->entries + database->entries_size);

size_t i_entry = database_entry - database->entries;
size_t count_to_move = (database->entries_size - 1) - i_entry;
size_t bytes_to_move = count_to_move * sizeof(spm_database_entry_t);
memmove(database_entry, database_entry + 1, bytes_to_move);                                                                          

大多数时候,bytes_to_move不会为 0,但如果为 0,则memmove()只会移动 0 个字节,不会造成任何伤害。因此,我们可以删除该if语句,除非您在其中有其他内容仅在移动发生时才需要执行。

此外,如果您这样做,并且仍然收到警告,您将获得一个行号,该行号将指出编译器所担心的问题。

于 2012-06-20T21:14:45.097 回答
0

我怀疑这个问题与size_t返回的sizeof(spm_database_entry_t), 始终是无符号类型(如果我没记错的话,通常只是unsigned intor的类型同义词)这一事实有关。unsigned long int但是,理论上存在一种可能性,即如果 的值database_entry超过该值database->entries + database->entries_size,您最终会将有符号数量乘以无符号类型,从而增加错误或整数溢出的可能性。通常,当有符号和无符号类型像这样混合时,较小的类型被强制转换/强制转换为较大的类型,或者,如果它们的排名相同,则有符号类型被强制转换为无符号类型。我不知道您的其余代码是什么样的,因此很难提出改进建议。

于 2012-06-20T19:47:46.803 回答