so I am learning and trying to figure out memory allocation in c, in this piece of code, is the memory allocated correctly or no? Do I need to allocate the array too or is the array already allocated because everything that user inputs goes to the array(will be stored in the array)?
#include <stdio.h>
#include <stdlib.h>
int main() {
int i;
int arr[20];
int b;
int *ptr;
ptr = &b;
ptr = (int*) malloc(20 *sizeof(int));
//find largest element in array
printf("Enter the number of elements: ");
scanf("%d", &b);
if(ptr == NULL)
{
printf(" No memory allocated.");
exit(0);
}
for (i = 0; i < b; ++i) {
printf("Enter number%d: ", i + 1);
scanf("%d", &arr[i]);
}
for (i = 1; i < b; ++i) {
if (arr[0] < arr[i])
arr[0] = arr[i];
}
free(ptr);
printf("Largest element = %d", arr[0]);
return 0;
}
You can clean up the malloc call:
ptr = malloc( 20 * sizeof *ptr );
You don’t need to cast the result of malloc unless you using an ancient pre-C89 implementation or C++ (in which case you should use new/delete instead of malloc/free, or more preferably a container type like vector).
sizeof *ptr is equivalent to sizeof (int) in this case.
However, you aren’t actually using that memory - you allocate it and free it, but you never write anything to it.
You initially assign &b to ptr, but then you overwrite it with the result of the malloc call, so if you’re expecting that memory to be attached to b somehow, be aware that it isn’t.
Related
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!
I've been trying O(n ^2) sorting algorithm just to practice C, but have encountered this annoying "realloc(): invalid pointer" error and cannot figure out why. I've viewed other explanations but they have not helped too much.
#include <stdio.h>
#include <stdlib.h>
int* removeIndex(int* list, int index, int len){
for(int i = index; i < len - 1; i++){
list[i] = list[i+1];
}
return realloc(list, len - 1);
}
int* sort(int* unsorted, int len){
int* sorted = malloc(len * sizeof(int));
for(int placement = 0; placement < len; placement++){
int smallest_index = 0;
int smallest = unsorted[smallest_index];
int len_unsorted = len - placement;
for(int i = 0; i < len_unsorted; i++){
if (unsorted[i] < smallest){
smallest = unsorted[i];
smallest_index = i;
}
}
unsorted = removeIndex(unsorted, smallest_index, len_unsorted);
sorted[placement] = smallest;
}
return sorted;
}
int main()
{
int len = 5;
int unsorted[5] = {5,4,3,2,1};
int* sorted = sort(unsorted, len);
for(int i = 0; i < len; i++){
printf("%d\n", sorted[i]);
}
return 0;
}
On a side note, why do I get an error if I write
int len = 5;
int unsorted[len] = {5,4,3,2,1};
so I have to force write it as int unsorted[5] = {5,4,3,2,1};
Cheers
The pointer passed to realloc pointing to a array with auto storage duration, which is declared and initialized in main(), and not pointing to a memory block previously allocated with malloc, calloc or realloc.
From realloc [emphasis added]
Reallocates the given area of memory. It must be previously allocated by malloc(), calloc() or realloc() and not yet freed with a call to free or realloc. Otherwise, the results are undefined.
On top of the answer of H.S., I believe the sorting algorithm is ill designed. The first call to the function removeIndex is done with the parameters as so
removeIndex(unsorted, 4, 5)
The for loop is not entered and a reallocation is supposed to take place with realloc(list, 4).
As far as I can see the sorting algorithm cannot work in general. In particular the example you gave with 5,4,3,2,1.
Try to do that with pencil and paper and you will see what I mean.
So I was trying to pormpt the user to type in a number, and then store that value in a dynamic array. Here is the code first:
#include <stdio.h>
#include <stdlib.h>
//dynamically grow the array
void growArray(int *arr, int *size){
//double the size of the array
printf("Resizing array\n");
int *temp = malloc( *size * 2 * sizeof(int));
printf("Malloc was succesfuly\n");
int i;
for (i = 0; i < *size; i++)
temp[i] = arr[i];
printf("About to free arr\n");
printf("arr: %p", arr);
printf("temp: %p", temp);
free(arr);
arr = malloc( *size * 2 * sizeof(int));
printf("About to change value to arr\n");
arr = temp;
free(temp);
printf("About to change the value of size\n");
*size *= 2;
printf("New size: %d\n", *size);
}
int main(){
int *dynamicArr;
int *size;
*size = 1;
dynamicArr = (int*) malloc(sizeof(int));
int value, i;
i = 0;
do{
printf("\nPlease enter in a int value: ");
scanf("%d", &value);
//check if the array needs to be resizesd;
printf("Checking if size if sufficient\n");
if (i >= *size)
growArray(dynamicArr, size);
if (value != -999){
printf("Adding value to the array\n");
dynamicArr[i] = value;
i ++;
}
}while(value != -999);
for (i = 0; i < *size; i++){
printf("Value of dynamicArr[%d]: %d\n", i, dynamicArr[i]);
}
return 0;
}
As you can see, I have a bunch of print statements, that I so I can see at what point my program is at, and what it is current doing. So, the program initially works. I am able to add in 8 values successfully (and resize the array 3 times, going from size 1 to size 8). But when I add in my 9 value, it has to resize the array, in which the method growArray() is called. But, for some reason I get the following error:
*** Error in `./a.out': free(): invalid next size (fast): 0x0000000000e69010 ***
Segmentation fault (core dumped)
Before the error, the printf("About to free arr") works, but printf("arr: %p", arr); isn't called.
I have no idea why this is happening, some help would be much appreciated.
You code should probably look more like this:
#include <stdio.h>
#include <stdlib.h>
int main() {
int size = 1;
int *dynamicArr = malloc(size * sizeof(*dynamicArr));
int idx = 0;
while (1) {
int value;
printf("\nPlease enter in a int value: ");
scanf("%d", &value);
if (value == -999) {
break;
}
//check if the array needs to be resizesd
printf("Checking if size if sufficient\n");
if (idx >= size) {
size *= 2;
dynamicArr = realloc(dynamicArr, size * sizeof(*dynamicArr));
}
printf("Adding value to the array\n");
dynamicArr[idx++] = value;
}
int i;
for (i = 0; i < idx; i++) {
printf("Value of dynamicArr[%d]: %d\n", i, dynamicArr[i]);
}
free(dynamicArr);
return 0;
}
Or if you want to stick with your implementation:
#include <stdio.h>
#include <stdlib.h>
//dynamically grow the array
void growArray(int **arr, int *size){
//double the size of the array
printf("Resizing array\n");
int *temp = malloc( *size * 2 * sizeof(int));
printf("Malloc was succesfuly\n");
int i;
for (i = 0; i < *size; i++)
temp[i] = (*arr)[i];
printf("About to free arr\n");
printf("arr: %p\n", *arr);
printf("temp: %p\n", temp);
free(*arr);
printf("About to change value to arr\n");
*arr = temp;
printf("About to change the value of size\n");
*size *= 2;
printf("New size: %d\n", *size);
}
int main() {
int size = 1;
int *dynamicArr = malloc(size * sizeof(*dynamicArr));
int idx = 0;
while (1) {
int value;
printf("\nPlease enter in a int value: ");
scanf("%d", &value);
if (value == -999) {
break;
}
//check if the array needs to be resizesd;
printf("Checking if size if sufficient\n");
if (idx >= size) {
growArray(&dynamicArr, &size);
}
printf("Adding value to the array\n");
dynamicArr[idx++] = value;
}
int i;
for (i = 0; i < idx; i++){
printf("Value of dynamicArr[%d]: %d\n", i, dynamicArr[i]);
}
free(dynamicArr);
return 0;
}
BTW, you can use memcpy to copy the whole existing array to the temp array.
There are a couple of problems in your original code.
(a) The parameter arr is passed to growArray by value, so your assignments arr = malloc(...) and arr = temp are not updating the variable referenced in main() only the copy that is local to growArray. On the other hand, when you call free(arr) you are freeing the buffer pointed to by the variable dynamicArr in main(). This is the immediate cause of your segfault.
(b) When you assign arr = temp then free(temp); you leak the buffer you malloc()ed just above, then free the buffer you assigned arr to point to (leaving it dangling).
void growArray(int *arr, int *size){
When entering growArray, arr points to a buffer, A
...
int *temp = malloc( *size * 2 * sizeof(int));
temp is initialized to point to a new buffer, B
...
free(arr);
the original buffer, A, is freed. The local variable arr is now a dangling pointer, as is whatever pointer the caller holds that was passed into this routine by value.
arr = malloc( *size * 2 * sizeof(int));
arr is set to a freshly allocated buffer, C.
...
arr = temp;
arr is set to alias temp, pointing to the buffer B. The buffer C is leaked.
free(temp);
Buffer B, pointed to by both temp and arr is freed. They are both now dangling pointers. When arr is later
...
}
Both tmp and arr go out of scope. The buffers B and C are leaked.
int main(){
int *dynamicArr;
int *size;
*size = 1;
dynamicArr = (int*) malloc(sizeof(int));
dynamicArr points to a malloced buffer
...
do{
...
if(...){
growArray(dynamicArr, size);
...
}
The first time this if condition passes, the value of dynamicArr is passed as the argument arr to growArray. growArray frees the buffer it points to and then allocs and leaks some memory without affecting the local value of dynamicArr. dynamicArr is now a dangling pointer.
if (value != -999){
...
dynamicArr[i] = value;
And then this accesses the dangling pointer and segfaults.
What should I consider thinking about when understanding the output? Because right now my output is garbage for 20 integers and I dont know why. MY objective is to create 20 arrays with 30 integers in each one. So the final array will have integers of 19 to 48.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
int **p;//Declaration of a pointer variable
int i = 0, j;
int rows = 20;
int columns = 30;
p = (int**)malloc(20 * sizeof(int)); //First "bookend" allocates space
printf("Hello World! I have created a dynamic 20-array of 20x30 integers!\n");
if (p == NULL)
{
printf("Failed to allocated memory!");
exit(1);
}
for (i = 0; i < 20; i++)
{
if (p[i] == NULL)
{
printf("Integers not allocated! ");
}
p[i] = (int**)malloc(20 * sizeof(int));
}
for (i = 0; i < 20; i++)
{
for (j = 0; j < 20; j++)
{
if (p[j] == NULL)
{
printf("Integers not allocated! ");
}
p[i][j] = (int *)malloc(40 * sizeof(int));
}
printf("%d\n", p[(i+1)+j]);
}
free(p);
return 0;
}
I hope I got your question right...
What you are getting isn't exactly garbase... When doing p[i][j] = (int *)malloc(40 * sizeof(int)); you are just allocating one more array with 40 elements and putting it's address in p[i][j]... So when you try to print p[(i+1)+j] you are printing the address of that 40 elements array you malloc'd.
There are several issues with your code:
For the initial allocation, each element is an int *, so you need 20 * sizeof(int *), not 20 * sizeof(int).
Any space allocated by malloc is uninitialized, so attempting to read it is undefined behavior. If on the other hand you use calloc, that initializes the allocated memory to all 0.
You go through an extra set of loops attempting to allocate another array to each int location. If you were trying to create a 3D array (and defined p as int ***) that would work, but not for a 2D array.
Don't cast the return value of malloc, as that can mask subtle bugs.
If you want to dynamically allocate a 20 X 30 array of int, you do it like this:
// first allocate 20 int*
int **p = malloc(20 * sizeof(int *));
if (p == NULL) {
perror("malloc failed");
exit(1);
}
int i;
for (i=0;i<30;i++) {
// for each row, allocate 30 int
p[i] = malloc(30 * sizeof(int));
if (p[i] == NULL) {
perror("malloc failed");
exit(1);
}
}
Note that this doesn't set any values in the 2D array, it just allocates the memory for it.
For this code
#include <stdlib.h>
#include <stdio.h>
int *f (int n)
{
int *ptr = malloc (sizeof (int));
*ptr = n;
return ptr;
}
int main()
{
int i;
int **ptr = malloc (sizeof (int *));
ptr[0] = f (0);
for (i = 0; i < 5; ++i)
{
ptr = realloc (sizeof (int *) * (i + 2));
ptr[i + 1] = malloc (sizeof (int));
ptr[i + 1] = f (i + 1);
}
for (i = 0; i < 5; ++i)
{
printf ("%d\n", *ptr[i]);
free (ptr[i]);
}
free (ptr);
return 0;
}
does program allocate twice than it is needed?
Yes, You don't need the malloc in main as it is immediately overwritten on the next line and you leak that memory. Is this a homework question?
EDIT for question change
This is now leaking memory in an odd way.
The first few lines aren't leaking but when you get into the loop you're allocating and assigning randomly. (As a first, realloc takes as it's first arguement a pointer to reallocate, so you're missing ptr in there)
Now you're allocating ptr to be of size 2, then 3 then 4 etc... up to 6. And then immediately leaking that memory as you overwrite the pointer with the call to f()
You could write that all like this:
int i;
int **ptr = malloc (sizeof(int*) * 6);
for (i = 0; i < 6; ++i)
{
ptr[i] = f(i);
}
for (i = 0; i < 6; ++i)
{
printf ("%d\n", *ptr[i]);
free (ptr[i]);
}
free (ptr);
return 0;
As an aside, you should in general try not to allocate memory too often, it is relatively slow. If you can use the stack you should, and if not, try and allocate all the memory you need up front, calling realloc in a loop is a bad idea and should be avoided.
In this specific case you don't need a pointer to a pointer, you could have just allocated one array of 6 integers, with int* array = malloc(sizeof(int) * 6) and then array[0] = 0; which would be easier and better.
Yes, it does allocate twice the needed memory. Also, the value of "ptr" in main is overwrite by return of "f" so you don't even have a chance to free it. You could remove the call to malloc in "main":
int main()
{
int *ptr = f (3);
printf ("%d\n", *ptr);
free (ptr);
return 0;
}