问题 是否有任何情况下C4172 Visual C ++警告不应被视为错误?


C4172 当函数返回本地或临时地址或对局部变量的引用时的情况的Visual C ++警告。

像这样的东西:

int& fun()
{
    int var;
    return var; //C4172
}

现在看来使用是个好主意 #pragma warning 使Visual C ++将C4172视为错误并中断编译。

是否存在C4172实际上不是错误的理智场景?


1226
2018-02-04 15:45


起源

很可能不是,并且编译器将其作为诊断而不是编译错误提供是正确的,因为返回对本地的引用而不是语言语法错误是未定义的行为。为什么没有定义为语言语法错误?因为它不是语法错误。 - Alok Save
@Alok如果它是UB,编译器完全有权将其视为错误。 - Konrad Rudolph
@Alok但这不是问题。 (此外,您反复提及“语法”是一个红色的鲱鱼,还有其他类型的错误 必须 被诊断出来。) - Konrad Rudolph
语言规范允许这样的程序进行编译,因此编译器只想遵循该规范。也许它有一些特殊的标志,您可以在其中更改该行为,但默认情况下,它不应该拒绝有效的代码。 - PlasmaHH
@Alok但是,再次,这根本不是问题。问题是它是否有意义 从用户的角度来看 无论标准是否允许代码,始终将此警告视为错误。那是完全不同的。 - Konrad Rudolph


答案:


我不确定为什么有人会这样做:

int * stackTester()
{
    int dummy;
    return &dummy;
}

bool stackGoesUp()
{
    int dummy;
    return stackTester() > &dummy;
}

但一般来说,您应该将警告视为错误。


8
2018-02-04 15:53



一个稍微更健全的例子:找出最小堆栈帧的大小(=返回地址的大小?) - Konrad Rudolph
如果我理解C标准,将指针与>,<,> =和<=进行比较会导致未定义的行为,如果这些指针不指向同一个聚合对象(struct / union)或同一个数组的元素(包括非最后一个之后存在的元素)。我认为C ++在这里是一样的。 - Alexey Frunze
@AlexeyFrunze:是的, 但  std::less<T> 是为指针定义的,即使它们没有指向同一个数组的元素。 - Jerry Coffin


这是一级警告,很难忽​​视。但是编译器遵循这里的语言标准,不禁止调用UB。这是一个非常常见的错误,往往会达到一个好的结果。只要您不进行任何函数调用,指向堆栈的位置就会保持稳定。

处理此问题的最佳方法是始终将警告变为错误。使用/ WX编译,在IDE中将“将警告视为错误”设置。如果你故意想要压制一个警告,那么#pragma warning会让每个人都清楚地知道有什么可疑的事情,而不是意外。


4
2018-02-04 16:32





未使用的代码

class base
{
   virtual blah& makeBlah() 
}

class red : public base
{
    blah& makeBlah() { return blah(); } // there are no red blahs, never called
}

class blue : public base
{
    blah& makeBlah() { actual code to make a blah }
}

0
2018-04-04 16:27