C ++解析器源代码中的原因不明的错误

时间:2011-09-16 13:02:13

标签: c++ arrays parsing for-loop runtime-error

这是一个函数,它检查用户输入的函数的名称到我正在进行的解释器/解析器中,将它与函数数组进行比较,并执行相应的C ++函数。只要用户输入正确的函数名称,它就可以正常工作,但是如果没有用户输入的名称功能,解释器会以一些无法解释的运行时错误结束,即使我将其编程为打印“未定义的函数”然后继续解析循环:

void parser::eval_cmd(std::string& exp, pro::command fset[])
{
    expr = exp;
    exp_ptr = (char*) expr.c_str();

    bool found = false;

    for (int i = 0; i < (int)sizeof(fset); i++)
    {
        if (fset[i].check(expr))
        {
            found = true;
            exp_ptr = (char*)expr.c_str() + (fset[i].name.size() - 1);
            if (fset[i].cmd)
                fset[i].cmd(eval_args());
            break;
        }

    }

    if (!found) err::show(err::UNDEFINED);
}

我究竟做错了什么?

3 个答案:

答案 0 :(得分:7)

你做错了是(int)sizeof(fset)。这将为您提供指针的大小(以字节为单位),而不是传入的fset数组中的元素数。

您需要一些其他方法来确定数组中有多少元素,可能是通过传入另一个arg,使用std::容器而不是数组,或者使用NULL来终止数组。

例如,稍微更改您的函数定义:

void parser::eval_cmd(std::string& exp, const std::vector<pro::command>& fset)
{
    ...

    for (int i = 0; i < fset.size(); i++)
    {
        ... 

代码的其余部分保持不变。

<小时/> 编辑:我最好的建议是使用std::map<string, pro::command>并允许map管理查找算法,或std::vector<pro::comand>并使用上述算法不变。您可以测量内存性能,但我希望vector超过数组的唯一开销是静态数组上new ed数组的开销。

如果你的结论是不使用标准容器,这是我的第二好建议:

void parser::eval_cmd(std::string& exp, pro::command fset[], size_t count)
{
    ...

    for (int i = 0; i < count; i++)
    {

假设调用者知道(或可以确定)fset数组中的元素数量。 (请参阅Can this macro be converted to a function?获取相关帮助。)

答案 1 :(得分:2)

我看到一个即时错误,虽然没有看到更多的代码,我 不能确定症状可能是什么。你是循环控制 条件使用sizeof(fset)fset是一个指针,因此值将 永远是相同的(通常是4或8,取决于你是否在32岁 位或64位模式)。我fset的成员较少,那么你就会有 未定义的行为,如果它有更多,你将不会检查任何 后来的功能。

我的建议是std::map使用fset,然后跳过 完全循环。

答案 2 :(得分:0)

..., pro::command fset[])

相当于

..., pro::command *fset)

因此,当您执行sizeof(fset)时,它会计算sizeof(command*)而非实际sizeof(command)。如果您不知道fset[]大小,那么您可以编写template包装器:

template<unsigned int SIZE>  // <--- finds the sizeof fset
void parser::eval_cmd_array(std::string& exp, pro::command (&fset)[SIZE])
{
  void parser::eval_cmd(exp, fset, SIZE);  // <--- pass the size as 3rd param
}

现在你的原始函数中有数组大小;

void parser::eval_cmd(std::string& exp, pro::command fset[], unsigned int sizeof_fset)
{                                                          //^^^^^^^^^^^^^^^^^^^^^^^^^ 
 //...
   for (unsigned int i = 0; i < sizeof_fset; i++)
 //...  ^^^^^^^^ let it be unsigned :)
}