【问题标题】:Variable scope strange behavior in C++C ++中的变量范围奇怪行为
【发布时间】:2017-12-14 08:21:24
【问题描述】:

我的程序调用将在发生故障时设置errno 的方法,我像异常一样抛出errno 并捕获它:

try
{
    if (-1 == truncate("/foo/bar.txt", 0))
    {
        throw errno;
    }
}
catch (const int errno)
{
    //log
}

这里我不想讨论异常处理最佳实践话题。事实是在上面的代码中,当 catch 括号中的变量名是 errno 时,catch 块不会被命中。这个问题可以简化为:

try
{
    throw 1999;
}
catch (const int errno)  //renaming "errno" to "e" works!!!
{
    //unreachable code here 
}

我知道errno 是一个“特殊”名称,但我认为 C++ 可以正确处理在不同范围内定义的相同变量名称。

//test.h
int my_number = 99;

//test.cpp
#include "test.h"
int main()
{
    try
    {
        throw 1999;
    }
    catch(int my_number)
    {
        std::cout << "in catch: " << my_number << std::endl;   //prints 1999
    }

    std::cout << my_number << std::endl;  //prints 99
}

该程序是在 GNU5.4 中编译的(在 C++11 和 C++14 中都有)。谁能解释一下这种奇怪的行为?

【问题讨论】:

  • 符号errno 可能是一个预处理器宏
  • @Someprogrammerdude 这样吗?
  • 所以预处理器会将它替换它可能定义为的任何内容,所以你有例如const int something_which_is_not_valid_in_a_delcaration。简而言之,从不定义您自己的变量与保留符号同名。
  • 宏不关心作用域(这是它们的大问题之一)。
  • @Someprogrammerdude 那为什么会编译?

标签: c++ errno


【解决方案1】:

errno 是一个宏。因此,您的异常处理程序包含一些扩展标记,这些标记很可能没有什么意义。来自标准([errno]):

标头内容与POSIX标头相同 , 除了 errno 应定义为宏。

【讨论】:

  • 通常类似于(*__foo())。那会尝试捕获函数/函数指针吗?
  • @melpomene - 它会扩展到const int (*__foo())。如果我对声明符规则的回忆成立,那不是函数指针,而是函数。我不知道为什么在这种情况下 OP 的代码格式不正确。
  • @melpomene - 不得不使用cdecl。它确实声明了一个函数。
  • @DannyChen - 可能是因为您没有查看编译器实际使用的标头。
  • @DannyChen - VSCODE 可能是错误的。我建议您仅通过处理器传递该文件。例如g++ -E。看看另一边会发生什么。
猜你喜欢
  • 2014-09-24
  • 1970-01-01
  • 1970-01-01
  • 2012-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多