Lingbo Tang Lingbo Tang - 2 months ago 11
C Question

Memory copy and delete failed in C programming

I'm trying to split an randomly generated array in C. When I tried to print it out and check the data, it will always print the last chunk of data for me. And I will receive an free failure and the end of the running time:

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

#define N 100
#define CHUNK_COUNT 4


int main(){
long int * array = (long int *) malloc(sizeof(long int) *N);
int i;
int chunkSize = N/CHUNK_COUNT;
long int ** data = (long int **) malloc(sizeof(long int*) *CHUNK_COUNT);
srandom(time(NULL));
for (i = 0; i< N; i++)
{
array[i] = random();
}

for (i = 0; i<N; i++)
{
printf("%ld ",array[i]);
}

printf("\n");
for (i = 0; i< CHUNK_COUNT; i++)
{
long int *subArr = (long int*) malloc(sizeof(long int)*chunkSize);
memcpy(subArr, &array[i*chunkSize], chunkSize*sizeof(long int));
data[i] =subArr;
free((void *)subArr);
}

for (i = 0; i < CHUNK_COUNT; i++)
{
printf("Array %d: \n",i);
for(int j =0;j< chunkSize; j++)
{
if (j == 0 ) {printf("[ ");}
printf("%ld ",data[i][j]);
if (j==chunkSize-1) {printf("]\n");}
}
}

free((void *) array);
for (i = 0; i < CHUNK_COUNT; i++)
{
free((void*)data[i]);
}
free((void *) data);



}


When I debugging my code, I can see the chunk index is correct, but it will always print the last chunk of the entire data. However, when I print it inside the for loop that I memcpy long integers, it will print the correct results. Also, I received this error:


* Error in `./test': double free or corruption (top): 0x0000000000ec4370 *
Aborted (core dumped)


When I use gnu99 to compile it:

gcc -std=gnu99 -o test testSplit.c -g


And when I run it in gdb, I could only get an
__GI_raise
error. Anyone has ideas?

Answer

As the commenters already showed the error (keeping the adress instead of the actual content) let me show a possible solution.

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

#define N 100
#define CHUNK_COUNT 4


int main()
{
  // don't cast malloc() in C (you may do in O++)
  long int *array = malloc(sizeof(long int) * N);
  int i;
  int chunkSize = N / CHUNK_COUNT;
  long int **data = malloc(sizeof(long int *) * CHUNK_COUNT);
  srand(time(NULL));
  for (i = 0; i < N; i++) {
    array[i] = rand();
  }

  for (i = 0; i < N; i++) {
    printf("%ld ", array[i]);
  }

  printf("\n");
  for (i = 0; i < CHUNK_COUNT; i++) {
    // no need for a temporary array , you can use the destination directly
    data[i] = malloc(sizeof(long int) * chunkSize);
    memcpy(data[i], &array[i * chunkSize], chunkSize * sizeof(long int));
  }

  for (i = 0; i < CHUNK_COUNT; i++) {
    printf("Array %d: \n", i);
    for (int j = 0; j < chunkSize; j++) {
      if (j == 0) {
        printf("[ ");
      }
      printf("%ld ", data[i][j]);
      if (j == chunkSize - 1) {
        printf("]\n");
      }
    }
  }

  free(array);
  for (i = 0; i < CHUNK_COUNT; i++) {
    // no need for casting here
    free(data[i]);
  }
  free(data);
}

It is almost always a good idea to keep things as simple as possible (but not simpler).

Comments