3

The following code gives me a terminated by signal SIGSEGV (Address boundary error):

void rec(int x, int *arr, int *size) {
  if (x < 0) {
      rec(-x, arr, size);
      return;
  }
  arr = realloc(arr, sizeof(int) * ++(*size));
  *(arr + (*size) - 1) = x % 10;
  if (x % 10 != x)
      rec(x / 10, arr, size);
}

int main() {
    int *arr = malloc(sizeof(int));
    int *size = malloc(sizeof(int));
    *size = 0;
    rec(20, arr, 0);
}

I already figured our that the arr counter in the main method won't hold the desired result, but I still can't understand why I'm getting an error.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Hilberto1
  • 248
  • 1
  • 3
  • 10
  • 1
    Do you know [Hilberto1](https://stackoverflow.com/users/14415734/hilberto1)? This code is very similar to https://stackoverflow.com/questions/66603006/c-address-boundary-error-in-small-code-snippet-beginner – Barmar Mar 12 '21 at 20:09
  • I think this is reposting a closed question – Dock Mar 12 '21 at 20:12
  • @Barmar your answer unfortunately didn't solve my problem – Hilberto1 Mar 12 '21 at 20:14
  • Because you have multiple errors, and I didn't notice the second one. – Barmar Mar 12 '21 at 20:15
  • 1
    Are you the same poster? If the duplicate didn't solve the problem, you should have requested that it be reopened. – Barmar Mar 12 '21 at 20:15

2 Answers2

3

Notice that you are passing NULL as third argument:

rec(20, arr, 0); // 0 is NULL

and you get a segfault dereferencing it:

arr = realloc(arr, sizeof(int) * ++(*size)); // here size is `NULL`

try with

rec(20, arr, size);
David Ranieri
  • 39,972
  • 7
  • 52
  • 94
  • sry I'm so lost, I didn't notice that I put a 0 there. Oh god, what a stupid mistake – Hilberto1 Mar 12 '21 at 20:09
  • 1
    Don't beat yourself up, @Descrates! I once was struggling to figure out why my data processing was giving me crazy results until I remembered that bytes have 8 bits and not 4. – Daniel Walker Mar 12 '21 at 20:11
  • 2
    BTW, there's no need to allocate `size` dynamically. Just declare `int size = 0;` and pass `&size`. – Barmar Mar 12 '21 at 20:11
0

For starters these memory allocations

int *arr = malloc(sizeof(int));
int *size = malloc(sizeof(int));

does not make a sense. They are redundant.

You could just write

int *arr = NULL;
size_t size = 0;

Secondly the variable size is declared but not used because instead of the variable you passed the integer constant 0

rec(20, arr, 0);

So within the function rec

void rec(int x, int *arr, int *size);

the pointer size was initializer by the null pointer constant 0. That is size is a null pointer within the function and using a null pointer to access memory results in undefined behavior.

Also you should pass the pointer to the function by reference. Otherwise passing it to the function does not make a great sense because the pointer in main will not be changed.

The code in main could look like

int *arr = NULL;
size_t size = 0;

rec( 20, &arr, &size );

Pay attention to that you should free all the allocated memory when it will not be used any more.

Correspondingly the function should be declared like

void rec(int x, int **arr, size_t *size);

Use the type size_t instead of the type int because this unsigned integer type is the type of the second argument of the function realloc.

In general to get the result of realloc you should use an intermediate variable because the function can return a null pointer and the current pointer will be lost.

Also pay attention to that the call of the function is unsafe and can result in an infinite recursion due to this if statement

  if (x < 0) {
      rec(-x, arr, size);
      return;
  }

when the user passes to the function the value of x equal to INT_MIN.

Consider the following demonstrative program.

#include <stdio.h>
#include <limits.h>

int main(void) 
{
    int x = INT_MIN;
    
    printf( "x = %d\n", x );
    printf( "-x = %d\n", -x );

    return 0;
}

Its output might look like

x = -2147483648
-x = -2147483648

As you can see negating the value of the variable x you get the same negative value. So maybe it is better to declare the first function parameter as having the type unsigned int.

Your function can look for example the following way as it is shown in the demonstrative program below.

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

int rec( unsigned int x, unsigned int **arr, size_t *size ) 
{
    const unsigned int Base = 10;
    
    unsigned int *tmp = realloc( *arr, sizeof( int ) * ++*size );
    int success = tmp != NULL;
    
    if ( success )
    {
        *arr = tmp; 
        *( *arr + *size - 1 ) = x % Base;
        if ( x % Base != x )
        {
            success = rec( x / Base, arr, size );
        }
    }
    
    return success;
}

int main(void) 
{
    unsigned int *arr = NULL;
    size_t size = 0;
    
    rec( 123456789, &arr, &size );
    
    for ( size_t i = 0; i < size; i++ )
    {
        printf( "%u", *( arr + i ) );
    }
    
    putchar( '\n');
    
    free( arr );
    
    return 0;
}

The program output is

987654321
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335