MSVC C6029 警告:缓冲区可能溢出,使用未经检查的值.检查缓冲区大小时,警告不会消失

MSVC C6029 Warning: possible buffer overrun, use of unchecked value. The warning does not disappear when checking the buffer size

本文关键字:缓冲区 警告 检查 消失 小时 C6029 溢出 MSVC      更新时间:2023-10-16

我的代码中有烦人的C6029警告(Microsoft网站上的错误描述(。

例如:

#include <cstdio> // fopen, fseek, fread, fclose
static constexpr size_t MAX_BUFFER_SIZE = 100;
void foo(const FILE* myFILE)
{
    double buffer[MAX_BUFFER_SIZE]{};
    size_t bufferSize = 0;
    std::fread(&bufferSize, sizeof(size_t), 1, myFILE);
    std::fread(buffer, sizeof(double), bufferSize, myFILE); // C6029 Warning.       
}

仅当观察到一个特定的检查时,它才会消失(如错误描述中的示例(:

#include <cstdio> // fopen, fseek, fread, fclose
static constexpr size_t MAX_BUFFER_SIZE = 100;
void foo(const FILE* myFILE)
{
    double buffer[MAX_BUFFER_SIZE]{};
    size_t bufferSize = 0;
    std::fread(&bufferSize, sizeof(size_t), 1, myFILE);  
    if(sizeof(double) * bufferSize > sizeof(buffer))
    {
        return;
    }
    std::fread(buffer, sizeof(double), bufferSize, myFILE); // No C6029 Warning.        
}

这样的解决方案不适合我,因为如果超过允许的值,我仍然需要从文件中读取其他内容。

但是,如果我检查等效情况,警告仍然存在:

#include <cstdio> // fopen, fseek, fread, fclose
static constexpr size_t MAX_BUFFER_SIZE = 100;
void foo(const FILE* myFILE)
{
    double buffer[MAX_BUFFER_SIZE]{};
    size_t bufferSize = 0;
    std::fread(&bufferSize, sizeof(size_t), 1, myFILE);    
    if(sizeof(double) * bufferSize <= sizeof(buffer))
    {
        std::fread(buffer, sizeof(double), bufferSize, myFILE); // C6029 Warning, again.
    }           
}

同时,如果您稍微修改Microsoft建议的检查以发生错误,警告将神奇地消失:

#include <cstdio> // fopen, fseek, fread, fclose
static constexpr size_t MAX_BUFFER_SIZE = 100;
void foo(const FILE* myFILE)
{
    double buffer[MAX_BUFFER_SIZE]{};
    size_t bufferSize = 0;
    std::fread(&bufferSize, sizeof(size_t), 1, myFILE);
    if(sizeof(double) * bufferSize <= sizeof(buffer))
    {
        // DO NOTHING...
    }   
    std::fread(buffer, sizeof(double), bufferSize, myFILE); // Wow, magic! No C6029 Warning.        
}

此错误警告让我非常恼火。当然,我根本不能注意它,但我仍然想以"合法"的方式摆脱它(最好在语法上不可怕(。

这样的解决方案不适合我,因为如果允许的值是 超过,我仍然需要从文件中读取其他内容。

然后不要std::fread没有缓冲区的有问题的部分。例如,您可以std::fseek它。或者,您可以动态分配足够大的缓冲区。

如果输入文件中的数据太大,您发布的第一个版本的foo将溢出缓冲区。 因此,编译器发出警告是非常正确的。

最好的解决方案可能是动态分配缓冲区(为简洁起见,省略了错误检查(:

void foo(FILE* myFILE)
{
    double *buffer;
    size_t bufferSize = 0;
    std::fread(&bufferSize, sizeof(size_t), 1, myFILE);
    buffer = new double [bufferSize];
    std::fread(buffer, sizeof(double), bufferSize, myFILE);
    ...
    delete [] buffer;
}

注意:不能将myFILE作为const传递 - fread需要修改对象。 此外,在这种情况下,结帐std::unique_ptr协助内存管理。