【问题标题】:Undefined variable when initialized in switch statement?在switch语句中初始化时未定义的变量?
【发布时间】:2013-11-25 20:06:23
【问题描述】:

这个问题本身就需要一个显而易见的答案。无论如何,这是我的代码的 sn-p...

    switch(cSet)...

    case 8:{ //Special Characters
        finalSet = special;
        char* charSet = new char[special.size() + 1];
        charSet[special.size()] = 0; //Append null terminator
        memcpy(charSet, special.c_str(), special.size());
        break;
    }

    case 9:{ //Alphnumeric and Special character
        finalSet = all;
        char* charSet = new char[all.size() + 1];
        charSet[all.size()] = 0; //Append null terminator
        memcpy(charSet, all.c_str(), all.size());
        break;
    }
    ...

请注意,finalSet 的类型为 std::string。我需要将其保存为字符数组。在这个语句之后,我在 switch 语句之外调用charSet

    for(int i = 0; charSet; i++)
         printf("%s", charSet[i]);

现在,很明显 switch 语句是有条件的,所以变量可能并不总是被声明。所以 Visual Studio 2012 抛出错误“charSet 未定义”。不过,按照我的 switch 语句结构的方式,charSet 将始终被定义,否则程序将在 default 情况下退出。

为了解决这个问题,我尝试在 switch 语句的范围之外声明 charSet。但是,当我这样做时,由于某种原因,编译器会引发读取访问错误。

我很好奇如何解决这个问题。

感谢任何建设性的意见。

在switch语句之外声明时的错误码:

`Unhandled exception at 0x0F6616B3 (msvcr110d.dll) in cuda_comb.exe: 0xC0000005: Access violation reading location 0x00000061.`

【问题讨论】:

  • 请详细显示其他错误。正如您所说,您应该声明 charSet 比 switch 语句大。
  • 当然,给我一点时间......
  • 您有两个不同的charSet 变量,在不同的范围内声明。当执行到达break 语句时,您分配给charSet 的任何值都将丢失,并且名称charSet 在封闭块之外不可见。而且你有内存泄漏。
  • 如果使用C++11,在一定程度上可以只使用std::string的缓冲区作为可修改的字符数组。
  • 看起来for 循环中的条件已关闭,您可能想要for (char *it = charSet; *it; ++it) printf("%c", *it); 之类的东西

标签: c++ switch-statement


【解决方案1】:
  1. 必须switch 之外声明charSet。当变量在 switch/case 中声明时,它会在 switch 结束时超出范围,即使声明变量的 case 已执行。
  2. 只要 charSet 不为 0,您的 for(int i = 0; charSet; i++) 就会循环,并且每次都会递增 i。因为您没有在内部更改charSet,因为它始终不会为0,因此最终charSet[i] 超出范围并给您读取访问错误。更改它,使其循环直到i 大于缓冲区的长度,或charSet[i] == '0'(终止空值)。例如:

    for(int i = 0; charSet[i]; i++) 
        printf("%c", charSet[i]);
    
  3. 还将printf 中的%s 更改为%c,因为您打印的是char,而不是char *。虽然,当您打印一个以空字符结尾的字符串时,您可以完全避免 for 循环:

    printf("%s", charSet);
    

【讨论】:

    【解决方案2】:

    你拿出来的时候有没有试过(在切换之前):

    char* charSet = 0;
    

    然后在所有 switch 语句中删除char *,所以

    char* charSet = new char[all.size() + 1];
    

    变成:

    charSet = new char[all.size() + 1];
    

    那么你的代码甚至可以检查(切换后):

    if (!charSet)
    {
      // handle odd case
    }
    

    【讨论】:

    • 你使用0而不是NULL有什么原因吗?
    • @nonsensickle 这是 C++,不是 C
    • @Slava 那么在这种情况下std::nullptr 不是更正确吗?您正在将整数值设置为指针,它不应该是正确的。
    • @GlennTeitelbaum 嗯,你们都让我到了那里。这是一个有效的论点。谢谢,我今天学到了一些新东西。
    【解决方案3】:

    您在每个 case 块上定义 charSet,尽管您在堆上为此数组分配了内存,但在这些块之外,charSet 引用未定义,因为构建器显示。

    请注意,通过这样做,如果您没有在 switch 块之外使用charSet,您将不会收到任何错误,但您会泄漏内存。

    我的意思是:

    switch(cSet)...
    
    case 8:{ //Special Characters
        finalSet = special;
        char* charSet = new char[special.size() + 1]; // <-- charSet definition
        charSet[special.size()] = 0; //Append null terminator
        memcpy(charSet, special.c_str(), special.size());
        break;
    } // <-- charSet reference lost, Memory leak
    
    case 9:{ //Alphnumeric and Special character
        finalSet = all;
        char* charSet = new char[all.size() + 1]; // charSet definition
        charSet[all.size()] = 0; //Append null terminator
        memcpy(charSet, all.c_str(), all.size());
        break;
    } // <-- charSet reference lost, Memory leak
    
    } // End of switch
    
        for(int i = 0; charSet; i++)
         printf("%s", charSet[i]); // <-- Error charSet is not defined
    

    对此的正确解决方案是在 switch 语句之外声明 charSet,这样您就不会丢失引用:

    char* charSet = NULL;
    switch(cSet)...
    
    case 8:{ //Special Characters
        finalSet = special;
        charSet = new char[special.size() + 1];
        charSet[special.size()] = 0; //Append null terminator
        memcpy(charSet, special.c_str(), special.size());
        break;
    }
    ...
    }
    
    if(charSet)
       printf("%s", charSet);
    

    请注意,当您打印带有“%s”的数组时,您可以直接使用charSet

    【讨论】:

    • 嗯,你也复制了他的错误。 printf("%s", charSet[i]); 应该是 printf("%c", charSet[i]); 不是吗?以及您没有循环的停止条件...尝试for(int i = 0; charSet[i]; i++)
    • @nonsensickle 别担心,这只是从原始源代码快速复制粘贴。回顾之后,我认为,为了代码的清洁,最好只使用一个printf
    【解决方案4】:

    据我了解,您的代码如下所示:

     switch(cSet){    
            case 8:{ //Special Characters           
               char* charSet  = new char[special.size() + 1];
               //code
               break;
              }
             case 9:{ //Special Characters           
               char* charSet = new char[all.size() + 1];
               //code
               break;
               }
            //other cases
         }
    
       for(int i = 0; charSet; i++)
             printf("%s", charSet[i]);
    

    在这种情况下,即使您为每种情况定义了 charset,您也将 charset 的范围限制为定义它的每种情况 - 您已经弄清楚并将指针声明移到 switch 之外 - 例如:

    char* charSet;
    switch(cSet){    
           //code
    }
    

    您收到的错误基本上是说您正在从无效的内存位置读取。如果您不将指针分配给动态分配的内存位置,则会发生这种情况。即使您似乎为 switch 语句的所有情况都分配了 charSet 内存,但不要忘记您也有一个默认情况。

    希望对你有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-01-13
      • 1970-01-01
      • 2020-08-25
      • 2021-08-11
      • 1970-01-01
      • 2020-06-29
      相关资源
      最近更新 更多