不同环境中程序输出的差异

时间:2014-08-04 19:56:42

标签: c compiler-errors backtracking

我是编码的新手,我正在尝试回溯一个示例问题来打印给定数字集合中的所有子集,其中成员总数等于给定值。

我面临一个非常奇怪的问题,下面的代码恰好运行良好,并在ideone.com等在线编译器上提供所需的输出,但在我的系统上输出错误。我能否解释为什么会发生这种情况以及可能的原因?

//works well on online compilers

#include<stdio.h>
#include<stdlib.h>

void printArray(int *a, int n)
{
    int i;
    for(i=0;i<n;i++)
        printf("%d ",a[i]);
    printf("\n");
    return;
}

void subsetSum(int *set, int *tuple, int setSize, int tupleSize, int current, int sum, int const target)
{
    if(sum==target)
    {
        printArray(tuple,tupleSize);
        subsetSum(set,tuple,setSize,tupleSize-1,current+1,sum-set[current],target);//call further for items excluding this one
    }
    else
    {
        int i;
        for(i=current;i<setSize;i++)
        {
            tuple[tupleSize]=set[i];    //add the ith node to tuple and move down for backtracking
            subsetSum(set,tuple,setSize,tupleSize+1,i+1,sum+set[i],target); ///after this backtrack to other possible nodes
        }
    }
    return;
}

void getSubsets(int *set, int size, int const target)
{
    int *tuple=(int*)malloc(size*sizeof(int));
    subsetSum(set,tuple,size,0,0,0,target);
    free(tuple);
    return;
}

int main(void)
{
    int weights[] = {10, 7, 5, 18, 12, 20, 15};
    int size = 7;
    getSubsets(weights, size, 32);
    return 0;
}

预期输出(与ideone一样)

10 7 15 
7 5 20 
5 12 15 
12 20 

pc上的错误输出

10 7 15 
10 7 
10 

7 5 20 
5 12 15 
5 12 
5 

12 20 

2 个答案:

答案 0 :(得分:2)

我相信您正在读取set[]数组的末尾(分配为tuple[]),这会导致未定义的行为(UB)。

  1. i=6setsize-1)。
  2. 时考虑for循环中的第一次
  3. 然后致电:

    subsetSum(set,tuple,setSize,tupleSize+1, (setsize-1)+1, sum+set[i],target);
    
  4. 这意味着在subsetSum()的函数调用current == setsize

  5. 假设您sum==target打印数组(很好)但是你做了:

    subsetSum(set,tuple,setSize,tupleSize-1, setsize+1, sum-set[setsize],target);
    

    set[setsize]电话中溢出。

  6. printArray()删除缓冲区溢出后删除递归函数调用,因此UB和工作正常。它最初在一个编译器/环境中“工作”的原因仅仅是由于UB的性质......有时它似乎正常工作。

答案 1 :(得分:0)

不确定为什么ideone版本似乎有用,但无论如何,我认为你不需要在第一个if块中使用这一行:

subsetSum(set,tuple,setSize,tupleSize-1,current+1,sum-set[current],target);//call further for items excluding this one

&#34;回溯&#34;每个堆栈层返回时都会发生。