为什么这个程序会崩溃,如果 SPLIT 在 4 和 7 之间

Why does this program crash, if SPLIT is between 4 and 7

我有一个任务,程序在大多数情况下都在运行,但是,如果我将 SPLIT 值设置在 4 到 7 之间,它就会崩溃(如果我更改 SIZE,则会在不同的值崩溃,但为了简单起见,让我们保持在 10)。

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

#define SIZE 10
#define SPLIT 4
#define LOW 0
#define HIGH 10

void generateArray(int data[],int size,int low, int high){
    srand(time(NULL));
    for(int i=0;i<size;++i){
        data[i]=rand()%(high-low+1)+low;
    }
}

int splitData(int arraySize, int startArray[], int splitPoint, int **firstNewArray, int **secondNewArray){
    if(arraySize < 1){
        return -1;
    }
    if(splitPoint < 1 || (splitPoint >= arraySize)){
        return -1;
    }
    if(*firstNewArray != NULL || *secondNewArray != NULL){
        return -1;
    }
    *firstNewArray = malloc(splitPoint * sizeof(int));
    *secondNewArray = malloc((arraySize - splitPoint) * sizeof(int));
    for(int i = 0; i < arraySize; ++i){
        if(i < splitPoint){
                (*firstNewArray)[i] = startArray[i];
                printf("%d\n",startArray[i]);
        }else{
                (*secondNewArray)[i] = startArray[i];
                printf("%d\n",startArray[i]);
     }
    }
    return 0;
}

int main(){
    int arraySize = SIZE ;
    int *startArray = malloc(arraySize * sizeof(int));
    generateArray(startArray,arraySize,LOW,HIGH);
    int splitPoint = SPLIT;
    int *firstNewArray = NULL;
    int *secondNewArray = NULL;
    int result;
    result = splitData(arraySize, startArray, splitPoint, &firstNewArray, &secondNewArray);
    if(result == 0){
        for(int i = 0; i < arraySize; ++i){
            if(i < splitPoint){
                printf("First array number %d is %d\n",i+1,firstNewArray[i]);
            }else{
                printf("Second array number %d is %d\n",i,secondNewArray[i]);
            }
        }
        free(firstNewArray);
        free(secondNewArray);
    }

    free(startArray);
    return 0;
}

导致此行为的原因是什么?我该如何解决?任务是将 startArray 按值 SPLIT 拆分为 2 个新的动态数组,这将在函数 splitData 中创建,并且它们都可以在函数外部使用。

您的代码有两个问题

  1. 第一次显示结果时:

      for(int i = 0; i < arraySize; ++i){
         if(i < splitPoint){
             printf("First array number %d is %d\n",i+1,firstNewArray[i]);
         }else{
             printf("Second array number %d is %d\n",i,secondNewArray[i]);
         }
     }
    

如果数组大小太高或太低,这将无法正常工作,例如 splitPoint 为 9,这意味着 secondNewArray 大小为 1,但在此循环中,您访问的 secondNewArray[9] 应该为 0,您需要把循环改成这样

for(int i = 0; i < splitPoint; ++i){
  printf("First array number %d is %d\n",i+1,firstNewArray[i]);
}
for(int i = 0; i < SIZE - splitPoint; ++i){
  printf("Second array number %d is %d\n",i+splitPoint+1 ,secondNewArray[i]);
}
  1. 你的拆分函数有同样的问题:

     for(int i = 0; i < arraySize; ++i){
       if(i < splitPoint){
          (*firstNewArray)[i] = startArray[i];
          printf("%d\n",startArray[i]);
       }else{
          (*secondNewArray)[i] = startArray[i];
          printf("%d\n",startArray[i]);
       }
     }
    

在这种情况下,您也在访问数组大小之外的区域,假设拆分为 9,您将访问 secondNewArray[9] = startArray[9],而它应该是 secondNewArray[0] = startArray[9],要解决此问题,您需要在这里为每个数组使用不同的索引做同样的事情,代码应该是这样的:

int j = 0;
int k = 0;
for(int i = 0; i < arraySize; ++i){
  if(i < splitPoint) {
    (*firstNewArray)[j] = startArray[i];
    printf("%d\n",startArray[i]);
    j++;
  }
  else {
    (*secondNewArray)[k] = startArray[i];
    printf("%d\n",startArray[i]);
    k++;
  }
}

仔细看看下面的标记线

for(int i = 0; i < arraySize; ++i){
    if(i < splitPoint){
            (*firstNewArray)[i] = startArray[i];
            printf("%d\n",startArray[i]);
    }else{
            (*secondNewArray)[i] = startArray[i]; // LOOK HERE
            printf("%d\n",startArray[i]);
 }

假设数组大小为10,分割点为4,则*secondNewArray索引从0到5;但是,您试图分配元素 4 到 9,它们在数组的边界之外,导致 未定义的行为 。您需要调整 i 的值才能正确映射:

(*secondNewArray)[i - splitPoint] = startArray[i];