Search code examples
arrayscpointersmallocheap-memory

How to know heap overflow point?


I'm attempting to write a program that determines all palindrome within a given range. My program calls a function (number of digits) that returns the size of an integer (ie. 400 would be 3 as it has 3 digits), then (another - Splitis) returns a numbers place (ie. for 400, 3 would return 4 as that's the third digit. The program then stores the independant values on a pointer array. For example, (100 would be stored as 1,0,0). As the size of each element changes, you would have to use a double pointer, one for the total numbers, then one for each element based upon the size of the number. For some strange reason, I get a segmentation fault at when my array exceeds roughly 8000 pointers. Because it always fails at that point like clockwork and it seems to work better when I make malloc smaller, I'm assuming I'm overflowing the heap somehow. Anways, I'm trying to figure out why I keep getting a segfault? The code is below.

#include <stdio.h>
#include <stdlib.h>
#include "external file location"

int main(void)
{
double testsize=0;
int count=0;
int **currentarray;
int *innerarray=NULL;
size_t sizeofarray=9000;
currentarray=(int **)malloc(sizeof(int)*sizeofarray);
for(int A=0; A<sizeofarray; A++)
{
    size_t b=numberofdigits(&A);
    *(currentarray+A)=(int *)malloc(sizeof(int)*b*1);
    if(currentarray==NULL)
    {
    perror("malloc failed");
    }
    int c=0;
    for(c=b; c>=1; c--)
    {
    *(*(currentarray+A)+c)=SplitIs(A, c);       
    }
    if((*(*(currentarray+A)+1)==*(*(currentarray+A)+b)) && (b>1))
    {
    fprintf(stdout, "%d)", count++);
        for(int c=b; c>=1; c--)
        {
        fprintf(stdout, "%d", *(*(currentarray+A)+c));
        }
    putchar('\n');
    }
}
for(int i=0;i<sizeofarray; i++)
{
//free((currentarray+i)); //I haven't figured out how to free it yet as the pointer is contained in the above block.  Commented out for now.  A future question.
}
}

Solution

  • I have fixed up the issues I mentioned above, and your code seems to work without error. Note that I have supplied versions of numberofdigits and SplitIs, since you didn't supply them.

    You check for failure on the second malloc, but not the first.

    This would be a lot more reliable in C++.

    #include <stdio.h>
    #include <stdlib.h>
    
    int numberofdigits( int * x )
    {
        int c = 1;
        int d = 0;
        while( *x > c )
        {
            d += 1;
            c *= 10;
        }
        return d;
    }
    
    int SplitIs( int a, int c )
    {
        while( --c )
            a /= 10;
        return a % 10;
    }
    
    int main(void)
    {
        int count=0;
        int **currentarray;
        int *innerarray=NULL;
        size_t sizeofarray=9000;
        currentarray=(int **)malloc(sizeof(int*)*sizeofarray);
        for(int A=0; A<sizeofarray; A++)
        {
            int b=numberofdigits(&A);
            currentarray[A]=(int *)malloc(sizeof(int)*b+1);
            if(!currentarray)
            {
                perror("malloc failed");
            }
            int c=0;
            for(c=b; c>=1; c--)
            {
                currentarray[A][c]=SplitIs(A, c);       
            }
            if((currentarray[A][1]==currentarray[A][b]) && (b>1))
            {
                fprintf(stdout, "%d)", count++);
                for(int c=b; c>=1; c--)
                {
                    fprintf(stdout, "%d", currentarray[A][c]);
                }
                putchar('\n');
            }
        }
        for(int i=0;i<sizeofarray; i++)
        {
            free(currentarray[i]);
        }
        free(currentarray);
    }