Функция в C запускается для набора значений, но дает Ошибка сегментации: 11 для другого - PullRequest
0 голосов
/ 30 апреля 2020

Я пытаюсь найти уникальное ненулевое пересечение между двумя наборами. Я написал программу, которая работает для некоторого набора массивов, но дает ошибку сегментации для некоторых. Я пытался понять, почему, но потерпел неудачу, любая помощь будет высоко оценена. Дело в том, что определенные функции (NoRep и ComEle) работают нормально, но не могут вернуть значение назначенному указателю в случае, когда отображается ошибка сегмента. Ниже приведен код:

#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);
}

Еще раз спасибо за вашу помощь!

Ответы [ 2 ]

1 голос
/ 30 апреля 2020

Посмотрите на этот код:

   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++;
      }
   }

Здесь у вас есть вложенные циклы, т.е. for-l oop с while-l oop внутри. Итак, в худшем случае, во сколько раз можно увеличить cnt1?

Ответ: size_ar1 * size_ar2

Но ваш код резервирует только элемент size_ar1 + size_ar2 для CE1. Таким образом, вы можете закончить запись вне массива.

Это очень легко увидеть, напечатав cnt1 внутри l oop.

Другими словами - ваш CE1 слишком маленький. Это должно быть:

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

Но будьте осторожны - если входные массивы большие, VLA становится огромным, и вы можете столкнуться с переполнением стека. Рассмотрим динамическое выделение памяти c вместо массива.

0 голосов
/ 30 апреля 2020

Помимо принятого ответа: я пропустил оператор break в то время как l oop в функции ComEle. Это не давало мне ожидаемого значения 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++;

      }

   }

Это также избавит от необходимости большего массива или динамического распределения c, как это было предложено (и правильно) @ 4386427 * 1004. *

...