简体   繁体   English

递归调用分段故障问题

[英]Recursive call segmentation fault issue

quick question again. 再次快速提问。 I'm creating a recursive function that will look for elements in a array of "source" rules and apply those rules to an "target array" of rules if the "source" rule type is the same as the target character. 我正在创建一个递归函数,该函数将在“源”规则数组中查找元素,如果“源”规则类型与目标字符相同,则将这些规则应用于规则的“目标数组”。 Furthermore the function checks to see if the target character is in an array of symbols or not and adds it if it is not (and throws a few flags on the newly applied rule as well). 此外,该函数还会检查目标字符是否在符号数组中,如果不是,则将其添加(并在新应用的规则上抛出一些标志)。 This is all driven by a recursive call that uses a counter to determine how many iterations have passed and is used to determine the spot in the target array the new rule should be applied, so we don't overwrite. 这全部由递归调用驱动,该递归调用使用计数器来确定已进行了多少次迭代,并用于确定应应用新规则的目标数组中的位置,因此我们不会覆盖。

I've put in a little debugging code to show the results too. 我放入了一些调试代码来显示结果。

Here's the function itself: 这是函数本身:

//Recursively tack on any non terminal pointed elements 
int recursiveTack(rule * inrule[], char target, rule * targetrule[],
        int counter, char symbols[])
{

    printf("Got into recursiveTack\n");
    printf("target is %c\n", target);
    printf("counter is %d", counter);

    for (int k = 0; k < sizeof(inrule); k++)
    {

        if (inrule[k]->type == target)
        {

            //doublecheck to see if we're trying to overwrite
            if (targetrule[counter]->used = true)
            {
                counter++;
            }

            targetrule[counter]->head = inrule[k]->head;
            targetrule[counter]->type = inrule[k]->type;
            targetrule[counter]->used = true;

            //Check to see if the elements are new to the symbols table and need to be added
            if (!contains(returnGotoChar(targetrule[counter]), symbols))
            {

                //If not then add the new symbol
                addChar(returnGotoChar(targetrule[counter]), symbols);
                //Also set the goto status of the rule
                targetrule[counter]->needsGoto = true;
                //Also set the rule's currentGotoChar
                targetrule[counter]->currentGotoChar = returnGotoChar(
                        targetrule[counter]);
            }

            counter++;

            //recursivly add elements from non terminal nodes
            if (isNonTerm(targetrule[counter]))
            {
                char newTarget = returnGotoChar(targetrule[counter]);
                counter = recursiveTack(inrule, newTarget, targetrule, counter,
                        symbols);
            }
        }
    }

    //return how many elements we've added
    return counter;
}

Here's the call: 这是电话:

if(isNonTerm(I[i+first][second]))
{
    printf("Confirmed non termainal\n");
    printf("Second being passed: %d\n", second);
    //Adds each nonterminal rule to the rules for the  I[i+first] array
    second = recursiveTack(I[i], targetSymbol, I[i+first], second, symbols[first]);
}

All the arrays being passed in have been initialized prior to this point. 在此之前,所有传入的数组都已初始化。 However, the output I get indicates that the recursion is getting killed somewhere before it gets off the ground. 但是,我得到的输出表明递归在开始运行之前已被杀死。

Output: 输出:

Second being passed: 0
Confirmed non termainal
Got into recursiveTack
target is E
Segmentation fault

Any help would be great, I've got the rest of the program available too if needs be it's around 700 lines including comments though. 任何帮助都将是非常有用的,如果需要的话,我也可以使用该程序的其余部分,大约需要700行,包括注释。 I'm pretty sure this is just another case of missing something simple, but let me know what you think. 我敢肯定,这只是缺少简单内容的另一种情况,但请告诉我您的想法。

for(int k = 0; k < sizeof(inrule); k++)

sizeof(inrule) is going to return the size of a pointer type (4 or 8). sizeof(inrule)将返回指针类型的大小(4或8)。 Probably not what you want. 可能不是您想要的。 You need to pass the size of the arrays as parameters as well, if you are going to use these types of structures. 如果要使用这些类型的结构,则还需要传递数组的大小作为参数。

It would be better to use Standard Library containers like std::vector , though. 不过最好使用标准库容器,例如std::vector

if(targetrule[counter]->used = true){
 counter++;
  }

// what is the guarantee that targetrule[counter] is actually valid? // targetrule [counter]实际上有效的保证是什么? could you do a printf debug before and after it? 您可以在之前和之后进行printf调试吗?

The biggest thing I see here is: 我在这里看到的最大的事情是:

for(int k = 0; k < sizeof(inrule); k++)

This isn't going to do what you think. 这不会做您想的。 inrule is an array of pointers, so sizeof(inrule) is going to be the number of elements * sizeof(rule*). inrule是一个指针数组,因此sizeof(inrule)将成为元素数* sizeof(rule *)。 This could very quickly lead to running off the end of your array. 这可能很快导致耗尽阵列末端。

try changing that to: 尝试将其更改为:

for (int k = 0; k < sizeof(inrule) / sizeof(rule*); ++k)

Something else you might consider is an fflush(stdout); 您可能会考虑的另一件事是fflush(stdout); after your print statements. 在您的打印报表之后。 You're crashing while some output is still buffered so it's likely hiding where your crash is happening. 当某些输出仍在缓冲时您崩溃了,因此很可能隐藏崩溃发生的位置。

EDIT: 编辑:

That won't work. 那行不通。 If you had a function that did something like: 如果您有执行以下功能的函数:

int x[10];
for (int i = 0; i < sizeof(x) / sizeof(int); ++i) ...

It would work, but on the other side of the function call, the type degrades to int*, and sizeof(int*) is not the same as sizeof(int[10]). 可以,但是在函数调用的另一端,类型降级为int *,并且sizeof(int *)与sizeof(int [10])不同。 You either need to pass the size, or ... better yet, use vectors instead of arrays. 您要么需要传递大小,要么……更好地使用向量而不是数组。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM