Search code examples
carraysreallocsigabrt

C - Getting a SIGABRT error, does not make any sense for me


So, my program should read an array of unknown size of positive integers in the format {1,2,3,4,5}, process it into an array, and then start reading pairs of integers a and b and find the least common multiple of a to (b-1)th elements of that array. Here's my current solution:

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

int gcf(int a, int b) // greatest common divisor
{
    while (a*b!=0)
    {
        if (a<b)
            b=b-a;
        else
            if (b<a)
                a=a-b;
        else
            if (a==b)
                return a;
    }
    return 0;
}

int lcm(int a, int b) // least common multiplier
{
    return a*b/gcf(a,b);
}

int main()
{
    int a,bufUsed=0,bufCurr=0,i,b,signal=1,curlcm;
    char c;
    int* tmp;
    int* array;
    c=getchar();
    if (c!='{')
    {
        printf ("err0");
        return 0;
    }
    while((scanf("%d",&a))==1)
    {
        if (signal==0) // checking for the comma
        {
            printf("err1");
            return 0;
        }
        signal=0;
        printf("%d ",a); // displaying current values, used just for debugging
        if (bufUsed == bufCurr) //resizing the current array 
        {
           bufCurr += 20;
           tmp = (int*)realloc(array, bufCurr); // the line that causes trouble
           if (!tmp)
               printf("err2");
           array = tmp;
        }
        array[bufUsed] = a;
        bufUsed++;
        if (scanf(" %c",&c)==1) // checking for commas or closing bracket
        {
            if (c==',')
            {
                signal=1;
                continue;
            }
            if (c=='}')
                break;
            else
            {
                printf("err3");
                return 0;
            }
        }
        else
        {
            printf("err4");
            return 0;
        }
    }
    while ((scanf("%d %d",&a,&b))==2) // the second part, finding the LCM
    {
        curlcm=lcm(array[a],array[a+1]);
        for (i=2;i<b-a;i++)
        {
            curlcm=lcm(curlcm,array[a+i]);
        }
        printf("%d\n",curlcm);
    }
    return 0;
}

The line

tmp = (int*)realloc(array, bufCurr);

seems to be causing the SIGABRT, according to gdb, however, if I remove the second part of the program (finding the LCM while cycle), it works just fine. I've tried checking how the second part works with a defined array in the second program:

int main()
{
    int a,i,b,curlcm;
    int array[10];
    for (i=0;i<10;i++)
        array[i]=i+1;      
    scanf("%d %d",&a,&b);
    curlcm=lcm(array[a],array[a+1]);
    for (i=2;i<b-a;i++)
    {
        curlcm=lcm(curlcm,array[a+i]);
    }
    printf("%d",curlcm);
}

and it runs just fine as well.

So how come that combining these two causes the SIGABRT? I've tried checking if accessing the array causes the problem, however, this seems not to be the case as well. Thanks in advance for any suggestions.


Solution

  • As per the manual, the function

    void *realloc(void *ptr, size_t size);
    

    The realloc() function changes the size of the memory block pointed to by ptr to size bytes. The contents will be unchanged in the range from the start of the region up to the minimum of the old and new sizes. If the new size is larger than the old size, the added memory will not be initialized. If ptr is NULL, then the call is equivalent to malloc(size)

    In the program, we have

    int* array;
    ...
    tmp = (int*)realloc(array, bufCurr);
    

    calling realloc the first time, while the array pointer is not initialized.

    The memory manager try to read some internal data based on that random address (like the size of the segment vs the requested size) which leads to undefined behavior (crash in your case).

    As suggested, a simple solution consists of setting initially array to NULL, so that realloc does a simple malloc (since its ptr address is NULL).

    int *array = NULL;