在 C 中使用指针时出现地址边界错误

Getting address boundary error when working with pointers in C

下面的代码给了我一个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);
}

我已经知道 main 方法中的 arr 计数器不会保存所需的结果,但我仍然不明白为什么会出现错误。

请注意,您将 NULL 作为第三个参数传递:

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

你会得到一个取消引用它的段错误:

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

试试

rec(20, arr, size);

对于初学者来说,这些内存分配

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

没有意义。它们是多余的。

你可以直接写

int *arr = NULL;
size_t size = 0;

其次,声明了变量大小但未使用,因为您传递的不是变量而是整数常量 0

rec(20, arr, 0);

所以在函数内rec

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

指针 size 由空指针常量 0 初始化。也就是说 size 是函数内的空指针,使用空指针访问内存会导致未定义的行为。

您还应该通过引用将指针传递给函数。否则将它传递给函数没有多大意义,因为 main 中的指针不会改变。

main 中的代码可能类似于

int *arr = NULL;
size_t size = 0;

rec( 20, &arr, &size );

注意当不再使用分配的内存时,应释放所有内存。

相应地函数应该这样声明

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

使用类型size_t而不是类型int,因为这个无符号整数类型是函数realloc.

的第二个参数的类型

一般来说,要获得 realloc 的结果,您应该使用一个中间变量,因为该函数可以 return 一个空指针,而当前指针将会丢失。

还要注意函数的调用是不安全的,会因为这个if语句导致无限递归

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

当用户将 x 的值传递给函数时等于 INT_MIN

考虑以下演示程序。

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

它的输出可能看起来像

x = -2147483648
-x = -2147483648

如您所见,取负变量 x 的值会得到相同的负值。所以也许最好将第一个函数参数声明为 unsigned int.

类型

您的函数可以按照下面的演示程序所示的方式查找。

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

程序输出为

987654321