【问题标题】:A function in C runs for a set of values but gives Segmentation Fault: 11 for anotherC 中的函数针对一组值运行,但给出 Segmentation Fault: 11 for another
【发布时间】:2020-08-14 08:58:28
【问题描述】:

我试图在两组之间找到唯一的非零交集。我编写了一个程序,它适用于某些数组集,但会给某些数组带来分段错误。我一直试图找出原因但失败了,任何帮助都将受到极大的重视。问题是定义的函数(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 complete\n");


   // //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 complete\n");


}


//---------------- 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%d\n", CE[i]);}
   printf("ComEle: %p\n",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: %p\n",NR);

return(NR);
}

再次感谢您的帮助!

【问题讨论】:

  • 欢迎来到 SO。您是否尝试过使用调试器来帮助查找分段错误的根源?
  • @rtx13:不,很遗憾,我目前无法这样做。

标签: c arrays pointers segmentation-fault function-pointers


【解决方案1】:

看看这段代码:

   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 会变得很大,您可能会遇到堆栈溢出。考虑动态内存分配而不是数组。

【讨论】:

  • 非常感谢您的帮助!您的解决方案确实有效。如果我可能会问:我应该如何动态分配 CE1 来克服这种情况?就像我不必仍然分配相同的内存吗?你的意思是,我可以稍后在函数中释放它还是什么?再次感谢您的帮助!
  • @user3474947 动态分配:int* CE1 = malloc(temp1 * sizeof *CE1);,一旦您不再需要CE1,请执行free(CE1)。是的,它的内存量相同,但是您的堆栈(VLA 所在的位置)的大小有限。堆(动态内存所在的位置)要大得多。所以巨大的对象应该总是动态分配的。示例:void foo() { char hugeArray[20000000]; ...} 是你永远不应该做的事情!
  • 知道了!非常感谢! :)
【解决方案2】:

除了公认的答案:我在 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 建议(正确地)对更大数组或动态分配的要求

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-29
    • 1970-01-01
    • 1970-01-01
    • 2011-09-29
    • 2017-08-02
    • 1970-01-01
    • 2014-03-25
    相关资源
    最近更新 更多