首页 > 解决方案 > MSVC C6029 警告:可能的缓冲区溢出,使用未经检查的值。检查缓冲区大小时警告不会消失

问题描述

我的代码中有烦人的 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.
    }           
}

同时,如果你稍微修改微软推荐的检查,导致出现错误,警告就会神奇地消失:

#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.        
}

这个错误警告让我非常恼火。当然,我可以根本不注意它,但我仍然想以“合法”的方式摆脱它(最好不要在语法上很糟糕)。

标签: c++visual-c++warningsbuffer-overflow

解决方案


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;
}

注意:不能通过myFILEas const-fread需要修改对象。此外,在这种情况下,结帐std::unique_ptr以协助内存管理。


推荐阅读