I tried checking the addresses and its all looking normal, printing works and everything else works as well.
But when it tries to free the memory, the program crashes.
CODE:
#include <stdio.h>
#include <stdlib.h>
#define FIRST_DIM 2
#define SECOND_DIM 3
#define THIRD_DIM 2
#define TOTAL 12
void getNums(float* pArr);
void sortArr(float* pArr);
void printArr(float* pArr);
int main(void)
{
// Variable assignment
unsigned int i = 0, j = 0;
float*** pppArr = NULL;
// Memory assignment
pppArr = (float***)calloc(FIRST_DIM, sizeof(float**));
if (!(pppArr))
{
printf("Failed Allocating Memory..\n");
system("PAUSE");
return 1;
}
for (i = 0; i < FIRST_DIM; i++)
{
*(pppArr + i) = (float**)calloc(SECOND_DIM, sizeof(float*));
if (!(*(pppArr + i)))
{
printf("Failed Allocating Memory..\n");
system("PAUSE");
return 1;
}
}
for (i = 0; i < FIRST_DIM; i++)
{
for (j = 0; j < SECOND_DIM; j++)
{
*(*(pppArr + i) + j) = (float*)calloc(THIRD_DIM, sizeof(float));
if (!(*(*(pppArr + i) + j)))
{
printf("Failed Allocating Memory..\n");
system("PAUSE");
return 1;
}
printf("%p && %d\n", *(*(pppArr + i) + j), **(*(pppArr + i) + j));
}
}
printf("ASD");
// Getting numbers, sorting them and printing them out
getNums(**pppArr);
sortArr(**pppArr);
printArr(**pppArr);
// End of program
// Releasing memory
for (i = 0; i < FIRST_DIM; i++)
{
for (j = 0; j < SECOND_DIM; j++)
{
free(*(*(pppArr + i) + j));
}
}
for (i = 0; i < FIRST_DIM; i++)
{
printf("%p\n", *(pppArr + i));
free(*(pppArr + i));
}
free(pppArr);
system("pause");
return 0;
}
/* This function gets values for the given array from the user */
void getNums(float* pArr)
{
unsigned int i = 0;
for (i = 0; i < TOTAL; i++)
{
printf("Enter Number %d: ", i);
scanf("%f", pArr + i);
getchar();
}
}
/* This function prints out the given array */
void printArr(float* pArr)
{
unsigned int i = 0;
for (i = 0; i < TOTAL; i++)
{
printf("Number %d: %.2f\n", i, *(pArr + i));
}
}
/* This function sorts the given array from lowest to highest*/
void sortArr(float* pArr)
{
unsigned int i = 0, j = 0;
float temp = 0;
for (i = 0; i < TOTAL; i++)
{
for (j = 0; j < TOTAL - 1; j++)
{
if (*(pArr + j) > *(pArr + j + 1))
{
temp = *(pArr + j);
*(pArr + j) = *(pArr + j + 1);
*(pArr + j+ 1) = temp;
}
}
}
}
is there something im missing?
When you use pointers and dynamic allocation, the memory you allocate will most likely not be contiguous, but you will get separate memory areas for each allocation. That means when you treat it as one large contiguous memory area in your functions you exhibit undefined behavior.
An actual array, like
float arr[FIRST_DIM][SECOND_DIM][THIRD_DIM];
Now that will be contiguous.
See e.g. this old answer of mine for a more "graphical" explanation of the difference between arrays of arrays, and pointers to pointers.
This code is indexing out of bounds rather severely. The memory allocated for pppArr has three levels of indirection. It is not a multi-dimensional array (i.e., not an array of arrays), but is a pointer to an array of pointers to arrays of pointers. Three levels of indirection. There are 6 separate float slices, each with 2 contiguous elements (i.e., THIRD_DIM).
When calling getNums, sortArr, and printArr, you are passing **pppArr. This is equivalent to passing pppArr[0][0], which points to a single 2-element sequence of float values. The functions may only access THIRD_DIM elements, i.e. 2. Instead, they are trying to access 12 elements (i.e., TOTAL), which of course corrupts memory and leads to undefined behavior.
As far as I can tell, it looks like you're trying to access the storage as a single one-dimensional array. If so, then the easiest way to fix it is to eliminate 2 levels of indirection, and get rid of FIRST_DIM, SECOND_DIM, and THIRD_DIM, and just allocate a single, flat array with LENGTH elements. The pointer would have type float *.
Related
I am trying to create a subtract function using pointers for 2d array but when I run it I get
expression must have pointer-to-object type but it has type "int"C/C++(142)
Can anybody explain why i'm getting this error and what is a better way around this?
this is my code
Function to read array
int *readMatrix(int *arr)
{
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 4; ++j)
{
printf("row %d, col %d: ", i + 1, j + 1);
scanf("%d", &arr[i * 4 + j]);
}
}
printf("\n");
return arr;
}
Function to subtract 2 2d arrays
int *subM(int *arrA, int*arrB, int *arrC){
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 4; ++j)
{
//printf("row %d, col %d: ", i + 1, j + 1);
&arrC[i][j] = &arrA[i][j] - &arrB[i][j]; //code where I am getting error
}
}
return arrC;
}
Main Function
int main()
{
int arrA[3][4];
int arrB[3][4];
int arrC[3][4];
readMatrix(&arrA[3][4]);
readMatrix(&arrB[3][4]);
subM(&arrA[3][4],&arrB[3][4],&arrC[3][4]);
return 0;
}
I am new to StackOverflow. I'm sorry if I can't express myself that well, but I think I found the solution to your problem.
Let's look at this step-by-step.
When passing an array to a function, you do not need to write the subscripts.
That means that instead of this:
readMatrix(&arrA[3][4]);
Just write this:
readMatrix(arrA);
You can (actually, should) also remove the pointer operator (&) because when only the array name is used, it acts as a pointer automatically.
Let's now take a look at the definition of readMatrix.
int *readMatrix(int *arr)
Using pointers for multi-dimensional arrays is okay, but the compiler would spit out a lot of warnings.
The most standard way is using subscripts in the definition of the function:
int *readMatrixStandard(int arr[3][4])
{
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 4; ++j)
{
printf("row %d, col %d: ", i + 1, j + 1);
scanf("%d", &arr[i][j]);
}
}
printf("\n");
return arr;
}
The subscripts in subM
For your case, there are two ways to access a multi-dimensional array.
Either tell the compiler that this function takes an multi-dimensional array:
Instead of this:
int *subM(int *arrA, int*arrB, int *arrC)...
Do this:
int *subM(int arrA[3][4], int arrB[3][4], int arrC[3][4])...
The code would then look something like this:
int *subMMultiDimension(int arrA[3][4], int arrB[3][4], int arrC[3][4]){
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 4; ++j)
{
//printf("row %d, col %d: ", i + 1, j + 1);
arrC[i][j] = arrA[i][j] - arrB[i][j]; //code where I am getting error
printf("%5d", arrC[i][j]);
}
puts(""); // for newline
}
return arrC;
}
Or use some pointer magic that is exclusive to C/C++ :) (not to be combined with the solution above)
Instead of this:
int *subM(int *arrA, int*arrB, int *arrC){
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 4; ++j)
{
//printf("row %d, col %d: ", i + 1, j + 1);
&arrC[i][j] = &arrA[i][j] - &arrB[i][j]; //code where I am getting error
}
}
return arrC;
}
Try this:
int *subM(int *arrA, int *arrB, int *arrC){
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 4; ++j)
{
//printf("row %d, col %d: ", i + 1, j + 1);
arrC[i * 4 + j] = arrA[i * 4 + j] - arrB[i * 4 + j]; //code where I am getting error
}
}
return arrC;
}
Use one of the ways, but the first one seems to be more standard because the compiler doesn't throw warnings on the first one.
Return value
You probably see where this is going. I'm just slapping on the code now.
Instead of:
return arr;
return arrC;
I prefer this for less warnings:
return arr[0];
return arrC[0];
The reason is simple. It points pratically to the same address, but it lets the compiler keep the mouth shut.
I think that this was it. The final code would look like this:
#include <stdio.h>
int * readMatrixStandard(int arr[3][4])
{
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 4; ++j)
{
printf("row %d, col %d: ", i + 1, j + 1);
scanf("%d", &arr[i][j]);
}
}
printf("\n");
return arr[0];
}
int * subMMultiDimension(int arrA[3][4], int arrB[3][4], int arrC[3][4])
{
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 4; ++j)
{
//printf("row %d, col %d: ", i + 1, j + 1);
arrC[i][j] = arrA[i][j] - arrB[i][j]; //code where I am getting error
printf("%5d", arrC[i][j]);
}
puts(""); // for newline
}
return arrC[0];
}
int main(void) // I recommend to always write void here if you are not using
// an old compiler
{
int arrA[3][4];
int arrB[3][4];
int arrC[3][4];
readMatrixStandard(arrA);
readMatrixStandard(arrB);
subMMultiDimension(arrA,arrB,arrC);
return 0;
}
Compiles nicely without warnings.
These code snippets are just my recommendations. If you want to know the most standard way to do something in C, you will probably have to look it up. A good book is also recommended. For instance, I learnt C with C Primer Plus by Stephen Prata. A great book with a lot of examples and illustrations to help you understand the situation.
Sorry again for my English. Guess there is still a long way to go.
If I missed anything or made a mistake somewhere, please let me know.
Edit: It's Stephen Prata, not Stephan ;)
By definition of the subscript operator [], the expression
A[B]
is equivalent to:
*(A + B)
Therefore,
A[B][C]
is equivalent to:
*( *(A+B) + C )
If you apply this to the line
&arrC[i][j] = &arrA[i][j] - &arrB[i][j];
it is equivalent to:
&*( *(arrC+i) + j ) = &*( *(arrA+i) + j ) - &*( *(arrB+i) + j );
The expression
&*( *(arrC+i) + j ) )
is invalid, for the following reason:
The sub-expression
*(arrC+i)
has type int, because dereferencing an int * yields an int. Therefore, the sub-expression
*(arrC+i) + j
will also evaluate to an int.
After evaluation that sub-expression, you then attempt to dereference that int using the * operator, which is illegal. Only pointer types can be dereferenced.
The sub-expressions
*( *(arrA+i) + j )
and
*( *(arrB+i) + j )
have exactly the same problem. You are also dereferencing an int in both of these expressions.
The actual problem is that you declared the function subM with the following parameters:
int *subM(int *arrA, int *arrB, int *arrC)
In C, arrays are usually passed to functions by passing a (possibly decayed) pointer to the first element of the (outer) array.
The parameter type int * would therefore be correct if you were passing 1D arrays to the function, but it is incorrect for 2D arrays. This is because a pointer to the first element of the outer array of a 2D int array has the type int (*)[4] in your case, i.e. a pointer to a 1D array of 4 int elements. However, you are instead passing a pointer to a single int object (not an array), so you are passing the wrong type of pointer.
Therefore, you should change the parameter types to the following:
int *subM( int (*arrA)[4], int (*arrB)[4], int (*arrC)[4] )
It may be clearer to write this the following way:
int *subM( int arrA[3][4], int arrB[3][4], int arrC[3][4] )
Both lines are equivalent, because arrays decay to pointers when used as function parameters.
Also, you should change the way you are calling the function. You should change the line
subM(&arrA[3][4],&arrB[3][4],&arrC[3][4]);
to:
subM( arrA[3], arrB[3], arrC[3] );
Due to array to pointer decay, this line is equivalent to:
subM( &arrA[3][0], &arrB[3][0], &arrC[3][0] );
Several issues ...
readMatrix uses an int *arr arg [correctly]. But, we want this to be compatible with sumM
sumM uses int * args, but tries to use dereference them using 2D array syntax.
In sumM, using (e.g.) &arr[i][j] is the address of the element and not its value [which is what we want].
In main, we're passing (e.g.) &arr[3][4]. This points past the end of the array, so this is UB (undefined behavior). We want to pass the start address of the array (e.g. arr or &arr[0][0]).
No need to pass back pointers to the resultant arrays because the caller passes in the addresses as args.
Here is the refactored code. It is annotated:
#include <stdio.h>
// Function to read array
#if 0
int *
readMatrix(int *arr)
#else
void
readMatrix(int arr[3][4])
#endif
{
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 4; ++j) {
printf("row %d, col %d: ", i + 1, j + 1);
#if 0
scanf("%d", &arr[i * 4 + j]);
#else
scanf("%d", &arr[i][j]);
#endif
}
}
printf("\n");
#if 0
return arr;
#endif
}
// Function to subtract 2 2d arrays
#if 0
int *
subM(int *arrA, int *arrB, int *arrC)
#else
void
subM(int arrA[3][4], int arrB[3][4], int arrC[3][4])
#endif
{
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 4; ++j) {
// printf("row %d, col %d: ", i + 1, j + 1);
// NOTE/BUG: we want to use the _values_ and _not_ the _addresses_ of the
// array elements
#if 0
&arrC[i][j] = &arrA[i][j] - &arrB[i][j];
#else
arrC[i][j] = arrA[i][j] - arrB[i][j];
#endif
}
}
// NOTE/BUG: since caller passed in the array, it knows where it is
#if 0
return arrC;
#endif
}
// Main Function
int
main(void)
{
int arrA[3][4];
int arrB[3][4];
int arrC[3][4];
// NOTE/BUG: doing (e.g.) &arrA[3][4] points past the _end_ of the 2D array
// and, so, is UB (undefined behavior) -- we want to pass the start address
#if 0
readMatrix(&arrA[3][4]);
readMatrix(&arrB[3][4]);
subM(&arrA[3][4], &arrB[3][4], &arrC[3][4]);
#else
readMatrix(arrA);
readMatrix(arrB);
subM(arrA, arrB, arrC);
#endif
return 0;
}
In the above code, I've used cpp conditionals to denote old vs. new code:
#if 0
// old code
#else
// new code
#endif
#if 1
// new code
#endif
Note: this can be cleaned up by running the file through unifdef -k
This is C programming code that I have written. When I run this code it shows debug error the visual code is showing this warning as well.
Warning 6385 Reading invalid data from 'my_newarray': the readable size is '4' bytes, but '8' bytes may be read.
My code is:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int n;
printf("enter the size of an array: ");
scanf_s("%i", &n);
int my_array[] = { calloc((n + 1), sizeof(int)) };
int my_newarray[] = { calloc((n + 1), sizeof(int)) };
printf("enter only 0s and 1s n times:\n");
for (int i = 0; i < n; i++)
{
scanf_s("%i", &my_array);
}
for (int j = 0; j < n; j++)
{
if (my_array[j] > my_array[j + 1])
{
my_array[j] = my_newarray[j + 1];
}
}
for (int k = 0; k < (n+1); k++)
{
printf("%i\n", my_newarray[k]);
}
free(my_array);
free(my_newarray);
}
These declarations
int my_array[] = { calloc((n + 1), sizeof(int)) };
int my_newarray[] = { calloc((n + 1), sizeof(int)) };
are incorrect. In fact you are trying to create arrays with the element type int that have single elements that are initialized by a value of the type void * that is returned by calls of calloc.
You need to declare pointers like
int *my_array = calloc((n + 1), sizeof(int));
int *my_newarray = calloc((n + 1), sizeof(int));
Also this call
scanf_s("%i", &my_array);
is incorrect. It seems you mean either
scanf_s("%i", &my_array[i]);
or
scanf_s("%i", my_array + i);
That is you need to fill elements of the allocated array except the last element that was already zero initialized by using a call of calloc.
Also this assignment
my_array[j] = my_newarray[j + 1];
and the following loop
for (int k = 0; k < (n+1); k++)
{
printf("%i\n", my_newarray[k]);
}
do not make a great sense because all elements of the array my_newarray were zero-initialized by a call of calloc. So you could just write
my_array[j] = 0;
I made a structure who has two members (int and int**), and I return the pointer to this structure from one function to main(). It is fine to access the int value in the structure. However, in main() I got Segmentation fault : 11 when I tried to access the element of the 2D array.
#include<stdio.h>
#include<stdlib.h>
typedef struct Square {
int value;
int **array;
} Square;
Square * generate();
int main(int argc, char *argv[]){
Square *sqrptr = generate();
printf("%d\n", sqrptr -> value);
/* It prints 1 */
/* Print out the 2D array */
for (int i = 0; i < 3; i++){
for (int j = 0; j < 3 ; j++){
printf("%d ", *(*((sqrptr -> array) + i) + j));
}
printf("\n");
}
/* It gives segmentation fault */
return 0;
}
Square * generate(){
Square mySquare;
mySquare.value = 1;
mySquare.array = malloc(sizeof(int*) * 3);
/* Initialize the 2D array */
for (int i = 0; i < 3; i++){
*(mySquare.array + i) = malloc(sizeof(int) * 3);
for (int j = 0; j < 3; j++){
*(*(mySquare.array + i) + j) = 0;
}
}
/* Print out the 2D array */
for (int i = 0; i < 3; i++){
for (int j = 0; j < 3l ; j++){
printf("%d ", *(*(mySquare.array + i) + j));
}
printf("\n");
}
/* I can see the complete 2D array here */
Square *sqrptr = &mySquare;
return sqrptr;
}
I have tried to generate the Square in main(), and use one pointer of the structure to access my 2D array. It works fine, so I guess I have missed something when I use a pointer returned from other functions. On the other hand, I can access the int value successfully, so I have no clues now.
Could someone please explain the underlying reason for this segmentation fault? Thanks!
You're returning a pointer to a local variable (&mySquare). Stack memory (where local variables reside) is when the function returns, so the resulting pointer is pointing to invalid memory. Allocate the struct, and return the pointer to heap memory:
Square *my_square = malloc(sizeof *my_square);
//do stuff
return my_square;
Or pass a pointer to a stack variable as argument:
Square * generate(Square *my_square)
{
//in case pointer wasn't provided, allocate
if (my_square == NULL) {
my_square = malloc(sizeof *my_square);
if (!my_square)
return NULL; // or exit or whatever
}
//initialize members. To initialize array to 3x3 zero matrix, you can use:
for (int i=0;i<3;++i)
my_square.array[i] = calloc(3, sizeof *my_square->array[i]);
//or even, if you change array member to type int*:
my_square.array = calloc(3*3, sizeof *my_square->array);
//at the end:
return my_square;
}
The latter is arguably the most flexible solution: if you want to work on stack, you call the function like so:
Square my_stack_square;
generate(&my_stack_square);
If you need to use heap memory, you can use:
Square *my_heap_square = generate(NULL);
As Jonathan Leffler pointed out, for a small struct such as this, returning by value isn't too much of a cost. Getting a struct on heap can be achieved in the same way as returning any other type:
Square generate( void )
{
Square my_square;
//initialize
return my_square;
}
//call like so:
Square sq = generate();
The idea here is that you'll use a local variable in the generate function to create a new square, initialize the fields, and then return it. Because in C everything is passed by value, this essentially means the function will assign the value of the local variable from the generate function to the caller's scoped sq variable. For small structs such as this, that's perfectly fine.
What's more, a common thing for compilers to do is to optimise these kinds of functions to the equivalent of the second example I posted: Essentially your function will be creating a new Sqaure object on the stack memory of the caller. This can happen, that's not to say it will. It depends on the optimization levels used when compiling, and on the size of the struct you're returning.
Basically, if you want to keep the code as close to what you have now, it's probably easiest to stick to the first version (returning a heap pointer).
The more flexible approach is the second one (as it allows you to use stack and heap, depending on how you call the function).
For now, using the third approach is perfectly fine: the compiler will most likely optimize the code to whatever makes most sense anyway.
Try this:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct Square {
int value;
int **array;
} Square;
Square * generate();
int main(int argc, char *argv[]){
Square *sqrptr = generate();
printf("%d\n", sqrptr -> value);
/* It prints 1 */
/* Print out the 2D array */
int i,j;
for (i = 0; i < 3; i++){
for (j = 0; j < 3 ; j++){
printf("%d ", *(*((sqrptr -> array) + i) + j));
}
printf("\n");
}
/* It gives segmentation fault */
return 0;
}
Square * generate(){
Square* mySquare = (Square*) malloc(sizeof(Square)); //c++ compiler
//Square* mySquare = (void*) malloc(sizeof(Square)); //c compiler
mySquare->value = 1;
mySquare->array = malloc(sizeof(int*) * 3);
/* Initialize the 2D array */
int i,j;
for (i = 0; i < 3; i++){
*(mySquare->array + i) = malloc(sizeof(int) * 3);
for (j = 0; j < 3; j++){
*(*(mySquare->array + i) + j) = 0;
}
}
/* Print out the 2D array */
for (i = 0; i < 3; i++){
for (j = 0; j < 3l ; j++){
printf("%d ", *(*(mySquare->array + i) + j));
}
printf("\n");
}
/* I can see the complete 2D array here */
return mySquare;
}
This question already has answers here:
2D array dynamic memory allocation crashes [duplicate]
(2 answers)
Closed 6 years ago.
I'm a newbie trying to learn how to make dynamics arrays in C. The code doesn't give me any errors when I build it using code:blocks, but when I run it crashes. I think the crash has to do with the way I'm freeing my memory, because the code is giving me the desired output before crashing.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i, j;
int *p = (int *)malloc(sizeof(*p));
printf("Hello World! I have created a dynamic array of 20x30 integers! \n");
for (i = 0; i <= 19; i++)
{
p[i] = (int )malloc(sizeof(int*));
printf(" %2d ", i);
for (j = i + 1; j <= 29 + i; j++)
{
p[i] = 0;
printf("%2d", j);
}
printf("\n");
}
for (i = 0; i <= 19; i++);
{
free(p[i]);
}
free(p);
return 0;
}
Here's the problem.
First, your first malloc call allocates space for a 1-element array.
You'll want to change it from
int *p = (int *)malloc(sizeof(*p));
to
int *p = (int *)malloc(sizeof(int*) * 20);
And then your second malloc call is slightly incorrect as well.
p[i] = (int )malloc(sizeof(int*));
should be changed to
p[i] = (int *)malloc(sizeof(int));
You just put the asterisk in the wrong place.
Finally, you really only create a 20-element array. All you do in the inner for loop is assign each cell in the array the value 0 times. If you want to make a 20x30 array, you can always take the easy route and create a 1D array and use some math (which is ultimately what the compiler does with non-dynamic 2D arrays anyway):
int main()
{
int *p = (int *)malloc(sizeof(int) * 600);
...
for (i = 0; i <= 19; i++)
{
printf(" %2d ", i);
for (j = 0; j <= 29; j++)
{
p[i * 30 + j] = 0; // It's i * 30, not i * 20 because you have to skip the space that the 'j' dimension takes up.
printf("%2d", j);
}
printf("\n");
}
free((void*)p); //I found the program crashes without the void* cast
}
I've tested this code and it runs.
Hope this helps.
I'm working through an algorithms MOOC and have a small program that takes an array A of ints in arbitrary order, counts the number of inversions (an inversion being the number of pairs (i,j) of array indices with i<j and A[i] > A[j]).
Below is the code I've written. I'm trying to tackle it using a "divide and conquer" approach where we recursively split the input array into two halves, sort each half individually while counting the inversions and then merge the two halves.
The trick is I need to keep track of the number of inversions and sort the arrays, so I pass the original array around the various recursive calls as an argument to the function and pass the count of inversions as a return value.
The code executes correctly through the first set of recursive calls that successively divide and sort [1,5,3], however when I get to the 3rd invocation of mergeAndCountSplitInv it crashes at the line:
sortedArrayLeft = realloc(sortedArrayLeft, sizeof(int)*(rightLen + leftLen));
with the error:
malloc: *** error for object 0x100103abc: pointer being realloc'd was not allocated
I can't see where I'm not using malloc correctly and I've combed through this checking to see I'm doing the pointer arithmetic correctly and can't spot any errors, but clearly error(s) exist.
Any help is appreciated.
// main.c
// inversionInC
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// function to help with debugging array/pointer arithmetic
void logArrayLenAndContents (char *arrayName, int arrayToPrint[], int arrayLen){
printf("%s\n", arrayName);
printf("len:%d\n", arrayLen);
for (int idx = 0; idx < arrayLen; idx++) {
printf("array[%d]: %d\n", idx, arrayToPrint[idx]);
}
}
int mergeAndCountSplitInv(int sortedArrayLeft[], int leftLen, int sortedArrayRight[], int rightLen)
{
printf("Calling mergeAndCount with sortedArrayLeft:\n");
logArrayLenAndContents("left Array", sortedArrayLeft, leftLen);
printf("...and sortedArrayRight:\n");
logArrayLenAndContents("right Array", sortedArrayRight, rightLen);
int i = 0;
int j = 0;
int k = 0;
int v = 0; // num of split inversions
int* outArray;
outArray = malloc((leftLen + rightLen) * sizeof(int));
while (i < leftLen && j < rightLen) {
if (sortedArrayLeft[i] < sortedArrayRight[j]) {
outArray[k] = sortedArrayLeft[i];
i++;
} else{
outArray[k] = sortedArrayRight[j];
v += leftLen - i;
j++;
}
k++;
}
// if at the end of either array then append the remaining elements
if (i < leftLen) {
while (i < leftLen) {
outArray[k] = sortedArrayLeft[i];
i++;
k++;
}
}
if (j < rightLen) {
while (j < rightLen) {
outArray[k] = sortedArrayRight[j];
j++;
k++;
}
}
printf("Wrapping up mergeAndCount where outArray contains:\n");
logArrayLenAndContents("outArray", outArray, k);
sortedArrayLeft = realloc(sortedArrayLeft, sizeof(int)*(rightLen + leftLen));
return v;
}
int sortAndCount(int inArray[], int inLen){
printf("Calling sortAndCount with:\n");
logArrayLenAndContents("inArray", inArray, inLen);
if (inLen < 2) {
return 0;
}
int inArrayLenPart1 = ceil(inLen/2.0);
int inArrayLenPart2 = inLen - inArrayLenPart1;
int* rightArray = malloc(sizeof(int) * inArrayLenPart2);
rightArray = &inArray[inArrayLenPart1];
int x = sortAndCount(inArray, inArrayLenPart1);
printf("sortAndCount returned x = %d\n\n", x);
int y = sortAndCount(rightArray, inArrayLenPart2);
printf("sortAndCount returned y = %d\n\n", y);
int z = mergeAndCountSplitInv(inArray, inArrayLenPart1, rightArray, inArrayLenPart2);
printf("mergeAndCount returned z = %d\n", z);
return x+y+z;
}
int main(int argc, const char * argv[])
{
static int* testArray;
testArray = malloc(5 * sizeof(int));
for (int i = 0; i<=4; i++) {
testArray[0] = 1;
testArray[1] = 5;
testArray[2] = 3;
testArray[3] = 2;
testArray[4] = 4;
}
int x = sortAndCount(testArray, 5);
printf("x = %d\n", x);
return 0;
}
This happens because the value of sortedArrayLeft gets lost as soon as the function returns. The realocated value does not make it to the caller, so inArray of the sortAndCount may be pointing to freed memory if realloc needs to reallocate and copy.
In order to fix this, pass a pointer to the pointer, letting sortedArrayLeft to propagate back to inArray of sortAndCount:
int mergeAndCountSplitInv(int **sortedArrayLeft, int leftLen, int sortedArrayRight[], int rightLen) {
...
*sortedArrayLeft = realloc(*sortedArrayLeft, sizeof(int)*(rightLen + leftLen));
return v;
}
...
int sortAndCount(int **inArray, int inLen) {
...
int z = mergeAndCountSplitInv(inArray, inArrayLenPart1, rightArray, inArrayLenPart2);
}
...
int x = sortAndCount(&testArray, 5);