C中的一个函数为一组值运行,但为另一个值给出Segmentation Fault:11



我试图在两个集合之间找到唯一的非零交集。我写了一个程序,它适用于某些数组集,但对某些数组存在分段错误。我一直试图弄清楚为什么,但都失败了,任何帮助都将受到极大的重视。问题是定义的函数(NoRep和ComEle(工作正常,但在显示Seg Fault的情况下无法将值返回给指定的指针。以下是代码:

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

int* ComEle(int ar_1[], int size_ar1, int ar_2[], int size_ar2);
int* NoRep(int a[], int l1);
int main ()
{
// Case 1: Gives segmentation fault
int A[10] = {1,1,0,2,2,0,1,1,1,0};
int B[10] = {1,1,1,1,0,1,1,0,4,0};
int *C = ComEle(A,10,B,10); printf("check completen");

// //Case 2: Does not give segmentation fault
// int A[4] = {2,3,4,5};
// int B[4] = {1,2,3,4};
// int *C = ComEle(A,4,B,4); printf("check completen");

}

//---------------- Local Functions --------------------//
int* ComEle(int ar_1[], int size_ar1, int ar_2[], int size_ar2) {
// sort of intersection of two arrays but only for nonzero elements.
int i=0, j=0, cnt1 = 0;
int temp1 = size_ar1+size_ar2;
int CE1[temp1]; for(i=0;i<temp1;i++) {CE1[i] = 0;}
/* Size of CE1 is knowingly made big enough to accommodate repeating
common elements which can expand the size of resultant array to
values bigger than those for the individual arrays themselves! */
for(i=0;i<size_ar1;i++) {
j = 0;
while(j<size_ar2) {
if(ar_1[i]==ar_2[j] && ar_1[i]!=0) {
CE1[cnt1] = ar_1[i];
cnt1++;          
}
j++;
}
}
// Have to remove repeating elements.   
int *CE = NoRep(CE1, cnt1);
for(i=0;i<(CE[0]+1);i++) {printf("CE:t%dn", CE[i]);}
printf("ComEle: %pn",CE);
return(CE);
}
int* NoRep(int a[], int l1) {
int cnt = 0, i = 0, j =0;
int *NR; NR = (int*)calloc((l1), sizeof(int));
//int NR[l1]; for(i=0;i<l1;i++) {NR[i] = 0;}
for(i=0;i<l1;i++) {
j = 0;
while(j<i) {
if(a[i]==a[j]) {break;}
j++;
}
if(j == i) {
cnt++;
NR[cnt] = a[i];         
}
}
NR[0] = cnt;  // First element: # of relevant elements.
printf("NoRep: %pn",NR);
return(NR);
}

再次感谢您的帮助!

看看这个代码:

int temp1 = size_ar1+size_ar2;
int CE1[temp1]; for(i=0;i<temp1;i++) {CE1[i] = 0;}
/* Size of CE1 is knowingly made big enough to accommodate repeating
common elements which can expand the size of resultant array to
values bigger than those for the individual arrays themselves! */
for(i=0;i<size_ar1;i++) {
j = 0;
while(j<size_ar2) {
if(ar_1[i]==ar_2[j] && ar_1[i]!=0) {
CE1[cnt1] = ar_1[i];
cnt1++;          
}
j++;
}
}

这里有嵌套的循环,即内部有while循环的for循环。那么,在最坏的情况下,cnt1可以增加多少次?

答案是size_ar1 * size_ar2

但是您的代码只为CE1保留了size_ar1 + size_ar2元素。因此,您最终可能会在数组之外进行写入。

通过在循环中打印cnt1,您可以很容易地看到这一点。

换句话说,你的CE1太小了。应该是:

int temp1 = size_ar1*size_ar2;  // NOTICE: * instead of +
int CE1[temp1]; for(i=0;i<temp1;i++) {CE1[i] = 0;}

但这里要小心——如果输入数组很大,VLA就会变得很大,并且可能会导致堆栈溢出。考虑动态内存分配而不是数组。

除了公认的答案:我在ComEle函数的while循环中丢失了一个break语句。它没有给我预期的cnt1值。以下是正确的方法:

for(i=0;i<size_ar1;i++) {
j = 0;
while(j<size_ar2) {
if(ar_1[i]==ar_2[j] && ar_1[i]!=0) {
CE1[cnt1] = ar_1[i];
cnt1++;
break;
}
j++;
}
}

这也将消除@4386427 建议的对更大阵列或动态分配的要求(这是正确的(

最新更新