Any way to avoid warning C6386, without disabling it or Code Analysis altogether

青春壹個敷衍的年華 提交于 2021-02-10 07:57:09

问题


Visual Studio 2019 started showing Code Analysis warnings as in-editor green squiggles by default. These may be extremely useful for students learning C programming, because they catch classical mistakes, such as off by one array accesses.

Unfortunately false positives may completely ruin the learning experience and I fear that I will have to ask the students to disable the feature in order to avoid having them worry on non existing problems.

This short snippet doesn't cause any warning:

#include <stdlib.h>

int main(void)
{
    size_t n = 6;
    int *v = malloc(n * sizeof(int));
    if (v == NULL) {
        return 1;
    }
    for (size_t i = 0; i < n; ++i) {
        v[i] = i;
    }
    free(v);
    return 0;
}

Unfortunately, if you move the allocation in a function, like this:

#include <stdlib.h>

int *test(size_t n)
{
    int *v = malloc(n * sizeof(int));
    if (v == NULL) { 
        return NULL;
    }
    for (size_t i = 0; i < n; ++i) {
        v[i] = i;
    }
    return v;
}

int main(void)
{
    size_t n = 6;
    int *v = test(n);   
    free(v);
    return 0;
}

you get a warning C6386: Buffer overrun while writing to 'v': the writable size is 'n*sizeof(int)' bytes, but '8' bytes might be written.

Even reading on Stack Overflow, I don't get where the '8' comes from, but, more importantly, why it fails to recognize that i will never be out of range.

So the question is: is there a way to write this type of code in a way that will not generate the warning?

I know that I can go to Tools > Options > Text Editor > C/C++ > Experimental > Code Analysis and set Disable Code Analysis Squiggles to True, or use a #pragma warning(disable:6386), but I'd rather avoid it, and certainly avoid suggesting my students the latter.


回答1:


You can supress this warning (which could be considered a bug), simply by ensuring the value of n given to the malloc call has not "wrapped around" following overflow (as hinted at in the comment from Eric Postpischill).

To do this, you can replace the n argument by the seemingly bizarre max(n,0):

int* test(size_t n)
{
//  int* v = malloc(n * sizeof(int));         // Warning C6386 on v[i] = i
    int* v = malloc(max(n, 0) * sizeof(int)); // No warning
    if (v == NULL) {
        return NULL;
    }
    for (size_t i = 0; i < n; ++i) {
        v[i] = i;
    }
    return v;
}



回答2:


I really want to thank everybody for their contributions and I agree that it is a bug in the Code Analyzer (by looking on Microsoft web sites it has been "Closed - Lower Priority" two years ago...).

Adrian Mole max(n, 0) trick points to a way for coping with the warning in code, that is checking that n is greater than zero. The funny thing is that you can still use that zero for what n was supposed to be used. While the idea could be used for experienced programmers (that would probably disable the warning), as John Bollinger points out, it's not for students.

So, after telling the students that it's a bug and how to turn off the Code Analysis squiggles or disable the warning, I'd go with

int *test(size_t n)
{
    if (n == 0) {
        return NULL;
    }
    int *v = malloc(n * sizeof(int));
    if (v == NULL) {
        return NULL;
    }
    for (size_t i = 0; i < n; ++i) {
        v[i] = i;
    }
    return v;
}

Which may also be interpreted as: don't allow 0 elements allocation.



来源:https://stackoverflow.com/questions/64713842/any-way-to-avoid-warning-c6386-without-disabling-it-or-code-analysis-altogether

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!