C SegFault fixed by print? - c

I have the task to write a program in C. The program should be able to check for parameters and create arrays that are as big as the parameter I gave. I have to fill the array with random numbers. Works fine so far. Later on my task is to sort the array using pointers. First thing is I did not quite understand how pointers work but I made the sorting work so far. The only problem is, that I can only sort to a size of 4. If my parameter is bigger than 4 I get the first 4 numbers sorted and then a Segmentation fault. I cannot find the issue but the fun part is, that if I add a printf just to print my parameter again it works fine for any parameter I want! I do not know what is happening!
Here is the exact task again, because I think I didn't describe it that well:
To do this, create a dynamic pointer field of the same size and initialize it with pointers to the elements of the int field. When sorting, the pointers should now be sorted so that the first pointer points to the smallest int value, the second to the next largest value, and so on.
int main(int argc, char *argv[]) {
int *array;
int **arrpointer;
int size = atoi(argv[1]);
if (size == 0) {
fprintf(stderr, "Wrong parameter!\n");
return EXIT_FAILURE;
}
//printf("Array-Size : "); //First I had it with scanf, which works perfectly fine without a print
//scanf("%d", &size);
printf("Input%d", size); //This is the print I need somehow!
// allocate memory
array = (int *)malloc(size * sizeof(int)); // Init Array
arrpointer = (int **)malloc(size * sizeof(int)); // Init Pointer Array
//Check Pointer array
if (arrpointer != NULL) {
printf("Memory allocated\n\n");
} else {
fprintf(stderr, "\nNo free memory.\n");
return EXIT_FAILURE;
}
if (array != NULL) {
printf("Memory is allocated\n\n");
//Fill Array
for (int i = 0; i < size; i++) {
array[i] = rand() % 1000; //I know it is not random right now, will add later
int *temp = &array[i];
arrpointer[i] = temp; //Pointer fill
}
} else {
fprintf(stderr, "\nNo free memory to allocate.\n");
return EXIT_FAILURE;
}
shakersort(arrpointer, size); //Function to sort pointers
zeigeFeld(arrpointer, size); //Function to Print
free(array);
free(arrpointer);
return EXIT_SUCCESS;
}
I know its a bit confusing, I am sorry.
I will also add the code where I sort it below.
void swap(int **a, int **b) {
int ram;
ram = **a;
**a = **b;
**b = ram;
}
void shakersort(int **a, int n) {
int p, i;
for (p = 1; p <= n / 2; p++) {
for (i = p - 1; i < n - p; i++)
if (*a[i] > *a[i+1]) {
swap(&a[i], &a[i + 1]);
}
for (i = n - p - 1; i >= p; i--)
if (*a[i] < *a[i-1]) {
swap(&a[i], &a[i - 1]);
}
}
}
This is the code I tried to build for the pointers and it works fine so far.
I hope someone can help or give some input to why my print fixes the problem. I really dont understand!
Thank you for your time and help, let me know if I should add anything!

The program has undefined behavior because the allocation size is incorrect for the array:
arrpointer = (int **)malloc(size * sizeof(int));
allocates space for size integers, but it should allocate space for size pointers to int, which on 64-bit systems are larger than int. Use this instead:
arrpointer = (int **)malloc(size * sizeof(int *));
Or use the type of the destination pointer:
arrpointer = malloc(sizeof(*arrpointer) * size);
This latter syntax is much safer as it works for any non void pointer type.
Note however that this array of pointers is overkill for your purpose. You should just implement the sorting functions on arrays of int:
void swap(int *a, int *b) {
int ram = *a;
*a = *b;
*b = ram;
}
void shakersort(int *a, int n) {
int p, i;
for (p = 1; p <= n / 2; p++) {
for (i = p - 1; i < n - p; i++) {
if (a[i] > a[i + 1]) {
swap(&a[i], &a[i + 1]);
}
}
for (i = n - p - 1; i >= p; i--) {
if (a[i] < a[i - 1]) {
swap(&a[i], &a[i - 1]);
}
}
}
}
Whether the above code actually sorts the array is unclear to me, I never use shakersort.

why do you use pointers before printf??
first you need to know what the pointer is:
the pointer is some kind of variable that contains address of some another variable.
for example:
int b = 2;
int * a = &b;
a variable include the address of variable b. then if you print ((a)) it will give you hex number which is the address of b. if you print ((*a)), compiler will print what in the address that int the variable a and print the amount of number in address of cell b(that means 2).
now i guess you understand what the pointer is, look again at your code and correct the mistakes.

I updated my code from
arrpointer = (int **) malloc(size * sizeof(int));
to
arrpointer = malloc(sizeof *arrpointer * size);
And it works fine!
Thank you all for your help!

Related

Incorrect first value in array of pointers

The dynamicRandomMatrix function should return a pointer to an array of n pointers each of which points to an array of n random integers.
I got it to print mostly correct, except the first number in the array. This is the output:
n=3: -2084546528, 59, 45
Can anyone help me figure out why the first number in the array is so small? I think it must be something to do with local variables and access or something, but I am not sure.
int** dynamicRandomMatrix(int n){
int **ptr;
ptr = malloc(sizeof(int) * n);
for (int i = 0; i < n; i++) {
int *address = randomArray(n);
ptr[i] = address;
}
return ptr;
free (ptr);
}
int* randomArray(int n){
int *arr;
arr = malloc(sizeof(int) * n);
for (int i = 0; i < n; i++) {
int num = (rand() % (100 - 1 + 1)) + 1;
arr[i] = num;
}
return arr;
free(arr);
}
int main(){
int **ptr;
int i;
ptr = dynamicRandomMatrix(3);
printf("n=3: ");
for (i = 0; i < 3; i++) {
printf("%d, ", *ptr[i]);
}
return 0;
}
In your code,
ptr = malloc(sizeof(int) * n);
is not correct, each element in ptr array is expected to point to a int *, so it should be ptr = malloc(sizeof(int*) * n);. To avoid this, you can use the form:
ptr = malloc(sizeof(*ptr) * n);
That said, all your free(array); and free (ptr); are dead code, as upon encountering an unconditional return statement, code flow (execution) returns to the caller, and no further execution in that block (function) takes place. Your compiler should have warned about this issue. If not, use proper flags to enbale all warnings in your compiler settings.

Allocating memory to 2D array using an array of NULL (c)

thanks for taking the time in reading this.
In my question a "vector" is defined as a 1D dimensional array of integers.
Therefore an array of vectors would be a 2D dimensional array in which every vector can be of a different length.
I'm asked to use:
int** vectors- the 2D array
int size -an integer that represents how many vectors exist inside **vectors
int* sizes-a 1D array of integers that represents the length of the vectors
for example,for:
vectors = {{4,3,4,3},{11,22,33,44,55,66},NULL,{5},{3,33,333,33,3}}.
size is 5 (there are 5 vectors inside vectors).
sizes is {4,6,0,1,5} (4 is the length of the first vector and so on).
size is inputted by the user at the beginning of main() and **vectors&*sizes are dynimacilly allocated with size's value.
I'm asked to write the function:
int init(int ***vectors, int **sizes, int size) which initializes **vectors to be an array of NULLs and *sizes to be an array of zeros.
I came up with this code:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int init(int*** vectors, int** sizes, int size)
{
int i, k,j;
printf("check\n");
*vectors = (int**)malloc(size * sizeof(int*));
if (*vectors == NULL)
return 0;
for (i = 0; i < size; i++)
{
*(vectors + i) = NULL;
}
printf("check 2\n");
for (k = 0; k<size; k++)
{
if (*(vectors+k) != NULL)
printf("didn't work\n");
else
printf("current is null\n");
}
*sizes= (int*)malloc(size * sizeof(int));
if (*sizes == NULL)
return 0;
for (j= 0; j < size; j++)
{
*(sizes + j) = 0;
printf("%d ", *(sizes + j));
}
printf("\n");
return 1;
}
int main()
{
int size, i;
int** vectors = NULL;
int* sizes = NULL;
printf("\nPlease enter an amount of vectors:\n");
scanf("%d", &size);
printf("%d\n", init(&vectors, &sizes, size));
printf("size is %d now\n", size);
// for (i = 0; i < size; i++)
// printf("%d ", *(sizes+i));
printf("check 3\n");
free(sizes);
free(vectors);
printf("check 4\n");
printf("check 5\n");
return 0;
}
forgot to mention that init returns 0 if it fails to allocate memory and 1 otherwise.
printing the "checks" was so I could see where the program fails.
the problem is that no matter what,after printing the last check (check 5)
the program fails.(Run-Time Check Failure #2)
if anyone could help me understand what I'm doing wrong I would HIGHLY appreciate it.
thanks alot for reading and have an amazing day.
edit:
i also printed the array sizes/vectors inside init just to see if it prints zeros/nulls,i don't actually need to do it.
One problem of OP's code is in the pointer arithmetic. Given:
int ***vectors;
*vectors = malloc(size * sizeof(int*));
This loop:
for (i = 0; i < size; i++)
{
*(vectors + i) = NULL;
}
Would iterate over the next unallocated pointer to pointer to pointer to int, while what the OP needs is
for (i = 0; i < size; i++)
{
*(*vectors + i) = NULL; // or (*vectors)[i] = NULL;
}
The same holds in the following loops, where *(sizes + j) is used instead of *(*sizes + j) (or (*sizes)[j]).

Segmentation fault when accessing a 2D array in a structure whose pointer is returned from a function

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

realloc(): invalid next size and double free

As a homework, I'm supposed to create 2 functions that enable you to push and pop elements to an array that acts as a queue. We're supposed to do this dynamically allocating memory. My program is almost working, but sometimes when adding and removing too many elements, I get errors like "realloc(): invalid next size", double free (when I've only called the free function once) and some of the elements in the beginning of the queue are set to 0. For instance, if I first add 100 elements, then remove 90 and try to add another 20, I get "free(): invalid next size (fast): 0x0000000001ea6010".
What am I doing wrong here?
According to suggestions below I changed my functions to take a double pointer as an input for the array. That, however, now gives me a Segmentation fault - which means now I don't know what to look for at all...
#include <stdio.h>
#include <stdlib.h>
void enqueue(int **arr, int* lastElementIdx, size_t* totalElements, int element) {
if (*lastElementIdx >= *totalElements) { // check if memorry is sufficient, otherwise double
*totalElements *= 2;
int* temp = realloc(arr, (*totalElements * sizeof(int)));
if (temp == NULL) { // just in case realloc fails
printf("Allocation error\n");
} else {
*arr = temp;
}
}
if (*lastElementIdx <= *totalElements) {
*lastElementIdx += 1; // once everything is done: add element
*arr[*lastElementIdx] = element;
}
}
int dequeue(int **arr, int* lastElementIdx, size_t* totalElements) {
if (*lastElementIdx > -1) { // if queue is not empty...
int deleted = *arr[0]; // save deleted value first (in case it's still needed)
for (int i = 0; i <= *lastElementIdx; i++) { // shift all elements
*arr[i] = *arr[i + 1];
}
*lastElementIdx -= 1; // index is now decreased by 1
if (((*totalElements / 2) >= 10) && ((*lastElementIdx + 1) < (*totalElements / 2))) { // cut memory in half if not needed
*totalElements /= 2;
*arr = realloc(arr, (*totalElements * sizeof(int)));
int* temp = realloc(arr, (*totalElements * sizeof(int)));
if (temp == NULL) { // in case realloc fails
printf("Allocation error\n");
return 0;
} else {
*arr = temp;
}
}
return deleted;
} else { // if queue is empty, print that there's nothing to dequeue
printf("There are no elements inside the queue\n");
return 0;
}
}
void printQueue(int arr[], int lastElementIdx) {
for (int i = 0; i <= lastElementIdx; i++) { // print entire queue
printf("[%d] = %d\n", i, arr[i]);
}
printf("\n");
}
int main (void) {
size_t totalElements = 10; // number of needed elements at the time
int lastElementIdx = -1; // index of last element in queue at the time
int *arr = calloc(totalElements, sizeof(int));
int **arrpointer = &arr;
for (int i = 1; i < 101; i++) {
enqueue(arrpointer, &lastElementIdx, &totalElements, i);
}
printQueue(arr, lastElementIdx);
for (int i = 0; i < 90; i++) {
dequeue(arrpointer, &lastElementIdx, &totalElements);
}
printQueue(arr, lastElementIdx);
for (int i = 1; i < 21; i++) {
enqueue(arrpointer, &lastElementIdx, &totalElements, i);
}
printQueue(arr, lastElementIdx);
free(arr);
return EXIT_SUCCESS;
}
When you expand or contract the storage for your queue, you need to provide a pointer to the storage back to the caller. This is because realloc() does not necessarily resize a memory block in-place -- it may create a new, differently sized block elsewhere. It is permitted to do so even when it resizes to a smaller block, not only when it resizes to a larger one.
Your usage of variable temp gives the appearance that you are aware of this issue, but as #DerkHermann first observed, you mishandle the resulting pointer. Perhaps you meant to write something along the lines of
arr = temp;
instead. Even that is not sufficient, however. C has only pass-by-value, so if you modify the value of function parameter arr, that modification is visible only in the function (which receives in arr a copy of the value the caller passes). In the event that realloc() allocates a new block, that leaves the caller with an invalid pointer.
If you want your enqueue() and dequeue() functions to be able to resize the storage for the queue, then you must pass the pointer to that storage indirectly. The most straightforward way of doing that, given where you are now, would be to pass a double pointer, so that you can modify its referrent:
void enqueue(int **arr, int* lastElementIdx, size_t* totalElements, int element) {
/* ... */
*arr = temp;
/* ... */
}
Observe, however, that you are passing three separate pointers that among them represent the state of the queue. It would be cleaner to create a struct type that combines those details in one package, and to pass a pointer to an object of that type:
struct queue {
int *arr;
size_t capacity;
size_t last_element_index;
};
void enqueue(struct queue *queue, int element) {
/* ... */
queue->arr = temp;
/* ... */
}
Maybe it's not the only problem, but at least the following line does not what you seem to expect:
*temp = *arr;
It looks as if you want to replace arr with the result of the realloc, delivering it back to the calling function (as with your other inout arguments). But, arr is not an inout argument: It is an array of integers, not a pointer to an array of integers. What you are actually doing with your above line of code is to copy the first element of arr to the newly allocated memory range. That newly allocated memory range temp, then, is nevertheless forgotten, creating a memory leak.
Adding a double pointer to reallocate the space in the right places, changing the comparing function with size_t totalElements and fixing a few additional mistakes finally did the trick.
#include <stdio.h>
#include <stdlib.h>
void enqueue(int **arr, int* lastElementIdx, size_t* totalElements, int element) {
if (*lastElementIdx + 1 >= (int)(*totalElements) - 1) { // check if memorry is sufficient, otherwise double
*totalElements *= 2;
int* temp = realloc(*arr, (*totalElements * sizeof(int)));
if (temp == NULL) { // just in case realloc fails
printf("Allocation error\n");
} else {
*arr = temp;
}
}
if (*lastElementIdx + 1 <= (int)(*totalElements) - 1) {
*lastElementIdx += 1; // once everything is done and if there is now enough space: add element
(*arr)[*lastElementIdx] = element;
}
}
int dequeue(int **arr, int* lastElementIdx, size_t* totalElements) {
if (*lastElementIdx > -1) { // if queue is not empty...
int deleted = (*arr)[0]; // save deleted value first (in case it's still needed)
for (int i = 0; i <= *lastElementIdx; i++) { // shift all elements
(*arr)[i] = (*arr)[i + 1];
}
*lastElementIdx -= 1; // index is now decreased by 1
if (((*totalElements / 2) >= 10) && ((*lastElementIdx + 1) < (*totalElements / 2))) { // cut memory in half if not needed
*totalElements /= 2;
int* temp = realloc(*arr, (*totalElements * sizeof(int)));
if (temp == NULL) { // in case realloc fails
printf("Allocation error\n");
return 0;
} else {
*arr = temp;
}
}
return deleted;
} else { // if queue is empty, print that there's nothing to dequeue
printf("There are no elements inside the queue\n");
return 0;
}
}
void printQueue(int arr[], int lastElementIdx) {
for (int i = 0; i <= lastElementIdx; i++) { // print entire queue
printf("[%d] = %d\n", i, arr[i]);
}
printf("\n");
}
int main (void) {
size_t totalElements = 10; // number of needed elements at the time
int lastElementIdx = -1; // index of last element in queue at the time
int *arr = calloc(totalElements, sizeof(int));
int **arrpointer = &arr;
for (int i = 1; i < 101; i++) {
enqueue(arrpointer, &lastElementIdx, &totalElements, i);
}
printQueue(arr, lastElementIdx);
for (int i = 0; i < 102; i++) {
dequeue(arrpointer, &lastElementIdx, &totalElements);
}
printQueue(arr, lastElementIdx);
for (int i = 1; i < 21; i++) {
enqueue(arrpointer, &lastElementIdx, &totalElements, i);
}
printQueue(arr, lastElementIdx);
free(arr);
return EXIT_SUCCESS;
}

Freeing memory in subroutine of recursion in C

I would like to ask a question about freeing memory in C. I am implementing the mergeSort function as following:
Merge subroutine:
int* merge (int* array_left, unsigned int left_length, int* array_right, unsigned int right_length) {
unsigned int result_size = right_length + left_length;
int* result = malloc(result_size*sizeof(int));
int r = 0; // result index
// Iterate through all left and right array elements
int i = 0; // left index
int j = 0; // right index
while ( (i < left_length) && (j < right_length) ) {
if ( *(array_left+i) < *(array_right+j) ) {
*(result+r) = *(array_left+i);
i++;
} else {
*(result+r) = *(array_right+j);
j++;
}
r++;
}
// Fill the remaining elements to the result
if (i < left_length)
while (i < left_length) {
*(result+r) = *(array_left+i);
r++;
i++;
}
if (j < right_length)
while (j < right_length) {
*(result+r) = *(array_right+j);
r++;
j++;
}
return result;
}
MergeSort:
int* mergeSort(int* array, unsigned int length) {
// Base case
if (length <= 1)
return array;
// Middle element
unsigned int middle = length / 2;
int* array_right = mergeSort(array, middle);
int* array_left = mergeSort(&array[middle], length-middle);
// Result is merge from two shorted right and left array
int* result = merge(array_left, length-middle, array_right, middle);
return result;
}
The program runs correctly but I didn't free memory from my malloc calls and in fact I can't figure it out how to place free(). I tried to free array_right and array_left but I got error telling me I can only free the pointer directly allocated by malloc.
Please help! Thank you guys in advance.
You need to add
free(arrayLeft);
free(arrayRight);
and also malloc and copy the array even in case its length is one in mergeSort:
int* mergeSort(int* array, unsigned int length) {
// Base case
if (!length) return NULL;
if (length == 1) {
// Make a copy of a single-element array
int *tmp = malloc(sizeof(int));
*tmp = *array;
return tmp;
}
... // The rest of your code
}
This would ensure that the caller of mergeSort always owns the array that it gets back, and so he must free it in all cases.
The reason it didn't work when you tried it was that you did not make copies of trivial arrays, which resulted in double-freeing some of them.

Resources