This question already has answers here:
C - Accessing data AFTER memory has been free()ed?
(2 answers)
Closed 2 years ago.
I'm studying C and I'm seeing something that it's not clear to me.
Here's the code:
#include <stdlib.h>
#include <stdio.h>
int main(void) {
printf("I'm using malloc\n");
int size = 10000000;
int *arr = (int *)malloc(size * sizeof(int));
if (arr == NULL) {
printf("memory could not be allocated\n");
exit(EXIT_FAILURE);
}
for (int i = 0; i < size; i++) {
arr[i] = i;
}
printf("Check the memory of the process\n");
int c;
scanf("%d", &c);
printf("I'm using realloc\n");
int *newArr = realloc(arr, 5 * sizeof(int));
if (newArr == NULL) {
printf("memory could not be allocated\n");
exit(EXIT_FAILURE);
}
int d;
printf("Check the memory of the process\n");
scanf("%d", &d);
for (int i = 0; i < 15; i++) {
printf("%d\n", arr[i]);
}
free(newArr);
}
If I check the process running with top, I can see that the memory of the process shrinks because of the realloc operation, what I wasn't expecting is that the last for loop is actually printing the first 15 numbers from arr. I was expecting an error due to missing elements from 5 to 15.
I'm using malloc
Check the memory of the process
45
I'm using realloc
Check the memory of the process
45
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Can you explain to me how this is working?
After the reallocation, you forgot to assign arr with newArr and then you print values form the invalid arr. (UB no 1)
Secondly, even if you assign it (or only change the arr to newArr) in the printf you will access elements outside the array bounds - which is UB no 2
Related
I'm trying to write a beginner c code when you get unknown amount of integers from user and process them. Since it's is not valid to initialize a array of integers without deciding the size, i wonder if i could do some trick to make my code more efficient. Currently I'm initializing an array with size of 999 and ask user not to go beyond this border.
example code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a[999];
printf("After entering numbers enter -1 to stop: \n");
for(int i=0;i<999;i++)
{
printf("Enter number(%d): ",i+1);
scanf("%d",&a[i]);
if(a[i]==-1) break;
if(i==998)
{
printf("Max limit reached.");
break;
}
}
//some code for processing the numbers
}
2 options: a) ask the user how many items and use a Variable Length Array (added to Standard C in C99; made optional in C11) ... or b) use dynamic memory and keep growing the array.
option a)
printf("enter number of items: ");
fflush(stdout);
char input[100];
fgets(input, sizeof input, stdin); // error checking ommited
size_t n = strtol(input, 0, 10); // error checking ommited
int array[n]; // VLA
// use array
option b)
size_t reserved = 5; used = 0;
int *array = malloc(reserved * sizeof *array); // start with space for 5 items
for (;;) {
if (used == reserved) {
// grow array
reserved *= 2;
int *tmp = realloc(array, reserved * sizeof *tmp);
if (!tmp) exit(EXIT_FAILURE); // not enough memory
array = tmp;
}
array[used++] = getint(); // get integer from user/file/network/...
// find way to leave for loop
}
// optionaly shrink the array
if (used < reserved) {
int *tmp = realloc(array, used * sizeof *tmp);
if (!tmp) exit(EXIT_FAILURE);
array = tmp;
}
// use array
free(array);
Option b) is preferred if the number of items can be large so as to not cause a stack overflow.
One sensible option is to forget about scanf and use command-line arguments instead. Faster, potentially safer (if you add an upper-bounds check), less memory consumed.
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char* argv[])
{
if(argc < 2) // or if(argc < 2 || argc > SOME_UPPER_LIMIT)
return 0;
size_t size = argc-1;
int input [size];
for(size_t i=0; i<size; i++)
{
input[i] = strtol(argv[i+1],NULL,10);
printf("%d ", input[i]);
}
}
Execute as for example: myprog 12 34 56 78 -> Output 12 34 56 78.
you can use this also :
#define MAXSIZE 999
void getNums(int nums[]){
int i = 0, temp;
char c;
while(((c=getchar())!='\n') && (i < MAXSIZE-1)){
temp = c - '0';
nums[i] = temp;
i++;
}
nums[i] = '\0';
}
int main(){
int nums[MAXSIZE];
getNums(nums);
return 0;
}
I'm working in C
I have a struct called Entity and I create a dynamic array of that struct. Then I try to remove one element from the array but I don't get the behaviour I want.
Here is the code I'm using:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Entity
{
int x, y;
int velX, velY;
}Entity;
int remove_element(Entity** array, int sizeOfArray, int indexToRemove)
{
int i;
printf("Beginning processing. Array is currently: ");
for (i = 0; i < sizeOfArray; ++i)
printf("%d ", (*array)[i].x);
printf("\n");
Entity* temp = malloc((sizeOfArray - 1) * sizeof(Entity)); // allocate an array with a size 1 less than the current one
memmove(
temp,
*array,
(indexToRemove+1)*sizeof(Entity)); // copy everything BEFORE the index
memmove(
temp+indexToRemove,
(*array)+(indexToRemove+1),
(sizeOfArray - indexToRemove)*sizeof(Entity)); // copy everything AFTER the index
printf("Processing done. Array is currently: ");
for (i = 0; i < sizeOfArray - 1; ++i)
printf("%d ", (temp)[i].x);
printf("\n");
free (*array);
*array = temp;
return 0;
}
int main()
{
int i;
int howMany = 20;
Entity* test = malloc(howMany * sizeof(Entity*));
for (i = 0; i < howMany; ++i)
(test[i].x) = i;
remove_element(&test, howMany, 14);
--howMany;
return 0;
}
And the output I get :
Beginning processing. Array is currently: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Processing done. Array is currently: 0 1 2 3 4 1866386284 6 7 8 9 10 11 12 13 15 16 17 18 19
Then the program crashes at the free (*array); line.
I want my second line to be 0 1 2 3 4 5 6 7 8 9 10 11 12 13 15 16 17 18 19.
How could I solve my problem ?
First thing you have allocated memory space for holding 20 Enity*. Then you have dereferenced it (and the value it contained is indeterminate). This is undefined behavior. And all story ends here.
But let's analyze what you mostly wanted.
Entity* test = malloc(howMany * sizeof(Entity));
^^^^^^^
is what you wanted. Because only if you do this you will get the member elements x and so on.
Also if you are considering 0 indexing then the memmove calls should be
memmove(temp, *array, (indexToRemove)*sizeof(Entity));
memmove(temp+indexToRemove, (*array)+(indexToRemove+1),
(sizeOfArray - indexToRemove - 1)*sizeof(Entity));
These two changes will be enough to solve the problems you are facing and realizing the correct behavior. (If this is all there is in your code).
Also as per standard the main() should be declared like this in case it doesn't take any parameter int main(void). Free the dynamically allocated memory when you are done working with it. Also you should check the return value of malloc - in case it fails it returns NULL and you should handle that case.
Your offset calculations are off by one in both memmove instances. Use this instead:
// copy everything BEFORE the index
memmove(temp,
*array,
indexToRemove * sizeof(Entity));
// copy everything AFTER the index
memmove(temp + indexToRemove,
*array + indexToRemove + 1,
(sizeOfArray - indexToRemove - 1) * sizeof(Entity));
In main itself your memeory allocation is not done properly.if you are using double pointer you should allocate memory first for double pointer and than single pointer in loop one by one.
a little touch
remove element in any type of struct array
regards
int remove_element(void **input_ptr, int input_size, int index_remove, int struct_size)
{
void *temp_ptr;
temp_ptr = malloc((input_size - 1) * struct_size);
if (temp_ptr == 0)
return -1;
memmove(temp_ptr, *input_ptr, index_remove * struct_size);
memmove(temp_ptr + (index_remove * struct_size), (*input_ptr) + (index_remove + 1) * struct_size, (input_size - index_remove - 1) * struct_size);
free(*input_ptr);
*input_ptr = temp_ptr;
return 1;
}
usage example for question struct
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Entity
{
int x, y;
int velX, velY;
}Entity;
int remove_element(void **input_ptr, int input_size, int index_remove, int struct_size)
{
void *temp_ptr;
temp_ptr = malloc((input_size - 1) * struct_size);
if (temp_ptr == 0)
return -1;
memmove(temp_ptr, *input_ptr, index_remove * struct_size);
memmove(temp_ptr + (index_remove * struct_size), (*input_ptr) + (index_remove + 1) * struct_size, (input_size - index_remove - 1) * struct_size);
free(*input_ptr);
*input_ptr = temp_ptr;
return 1;
}
int main()
{
int i;
int howMany = 20;
Entity* test = malloc(howMany * sizeof(Entity));
for (i = 0; i < howMany; ++i)
{
(test[i].x) = i;
printf("test[%d].x = '%d'\n", i, test[i].x);
}
remove_element((void**)&test, howMany, 14, sizeof(Entity));
--howMany;
printf("Deleted index --- new array\n");
for (i = 0; i < howMany; ++i)
printf("test[%d].x = '%d'\n", i, test[i].x);
return 0;
}
This question already has answers here:
Dynamic allocation of 2D array within function (using pointers to return adress of allocated object)
(2 answers)
Closed 6 years ago.
I'm trying to create a two dimensional array but when i use free at the end of my program i always get "Segmentation fault (core dumped)" error. The sleep function is only used because i wanted to see if it crashes after creating the array or later, and the program crashes as soon as i use free(array)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void check(int number)
{
if(number < 0)
{
fprintf(stderr, "You cannot use a value below zero!\n");
}
}
int create_array(int **array, int size)
{
array = (int**)malloc(size * sizeof(int*));
for(int i = 0; i < size; i++)
{
array[i] = (int*)malloc(size * sizeof(int));
}
printf("Successfully created the array!\n");
printf("The size of the array is %d * %d = %d", size, size, sizeof(array) / sizeof(int));
return EXIT_SUCCESS;
}
int main(void)
{
int N;
printf("Please enter a value for N: ");
scanf("%d", & N);
check(N);
int R;
printf("Please enter a value for R: ");
scanf("%d", & R);
check(R);
int **array;
create_array(array, N);
sleep(1);
free(array);
return EXIT_SUCCESS;
}
You are only modifying a local copy of array in create_array() function. In order to be able to modify the pointer array in main(), you need to pass a pointer to it (i.e. the function needs to receive a int***).
More simply, you can return the array from the function and assign it to the array in main() and you wouldn't need to pass the first argument.
you are creating dynamic array but you are not returning the reference of that array, thats why you are failing to free it.
You need to call create_array() as follows:
int **array;
create_array( &array, N);
Then define it as:
int create_array(int*** array, int size)
{
*array = (int**)malloc(size * sizeof(int*));
for(int i = 0; i < size; i++)
{
(*array)[i] = (int*)malloc(size * sizeof(int));
}
printf("Successfully created the array!\n");
printf("The size of the array is %d * %d = %d", size, size, sizeof(array) / sizeof(int));
return EXIT_SUCCESS;
}
You will still have a memory leak however since you are only freeing array and not freeing array[0] to array[N-1]. It would be safer to create a corresponding destroy_array() function.
Please if someone tell me what is wrong with this code by using malloc function, I dont know what to do.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <process.h>
int main()
{
int row;
int column;
int j=0;
int **ptr;
printf("Number of rows: \n");
scanf ("%d",&row);
printf("Number of columns: \n");
scanf ("%d",&column);
There is a mistake, ???? please if someone know what to do to write
int* ptr = malloc( row * sizeof(*ptr) ); /*Allocate integer pointers for the rows */
if(ptr != NULL)
{
for(int m = 0; m < row; m++) /* Loop through each row pointer to allocate memory for columns*/
{
/* Set p[i] pointer to a block of memory for 'column' number of integers */
ptr[m] = malloc(column * sizeof **ptr); /*Here, sizeof(**p) is same as sizeof(int) */
if(ptr[m] == NULL)
{
printf("Memory allocation failed. Exiting....");
exit(1);
}
}
}
else
{
printf("Memory allocation failed. Exiting....");
exit(1);
}
for(int i=0; i<row; i++)
{
for(int j=0; j<column; j++)
{
printf("Enter values [%d] [%d]: \n",i+1,j+1 );
scanf ("%d",&ptr[i][j]);
}
}
free (ptr);
system("PAUSE");
return 0;
}
Pleas for answer because i need this code in school till 3. Jan. 2014
Change this line…
int* ptr = malloc( row * sizeof(*ptr) );
… to this…
ptr = malloc( row * sizeof(*ptr) );
You've already declared ptr here:
int **ptr;
If you feel the need to use malloc (and free) for dynamic allocation, then there are some good answers already here. But please consider that you do not need to use malloc at all in your example.
You can simply declare an automatic array of variable size as shown below. Your code will be very clear and the potential for bugs will be reduced. This feature is available in the C language since ISO C99 (earlier, in some compliers).
There can be an argument to not use variable sized array declaration if the array will be extremely large. Your example is taking user input for each array element, so that tells me you're not allocating hundreds of megabytes or anything that would blow up the stack! So this will work for you just fine. Good luck.
#include <stdio.h>
int main()
{
int rows;
int columns;
printf("Number rows: ");
scanf ("%d", &rows);
printf("Stevilo columns: ");
scanf ("%d", &columns);
int values[rows][columns]; /* <-- no need to malloc(), no need to free() */
for(int i=0; i<rows; i++) {
for(int j=0; j<columns; j++) {
printf("Enter value[%d][%d]: ",i+1,j+1 );
scanf("%d", &values[i][j]);
}
}
}
Instead of using sizeof (ptr) and sizeof **ptr, try to use sizeof(int*) in the first malloc, and sizeof(int) in the second malloc.
thank you all for so fast answers, it was very helpful, now it works without any error!
I did so:
int** ptr = (int**) malloc(row * sizeof(int)); /*Allocate integer pointers for the rows */
if(ptr != NULL)
{
for(int m = 0; m < row; m++) /* Loop through each row pointer to allocate memory for columns*/
{
/* Set p[i] pointer to a block of memory for 'column' number of integers */
ptr[m] = (int*)malloc(column * sizeof(int)); /*Here, sizeof(**p) is same as sizeof(int) */
if(ptr[m] == NULL)
{
printf("Memory allocation failed. Exiting....");
exit(1);
}
}
}
else
{
printf("Memory allocation failed. Exiting....");
exit(1);
}
First off your code is very messy. Your malloc call should also look like this for example:
int** ptr = (int**)malloc(row * sizeof(ptr*));
The size of a pointer will always (almost all the time unless you are on a computer made in 1982) be 4 because its a memory address aka an int wich is 4 bytes. In your for loop it should read something like:
ptr[m] = (int*)malloc(column * sizeof(ptr));
I should be allocating enough memory for my char**. I used gdb and found the point of the segmentation fault. I've been stuck on this part for about an hour and can't seem to figure out why I'm segfaulting.
Output of program:
size: 10, 20
start: 1, 1
end: 10, 20
Segmentation fault (core dumped)
10 = m1.xsize
20 = m1.ysize
1 = m1.xstart
1 = m1.ystart
10 = m1.xend
20 = m1.yend
snippet of my code:
typedef struct mazeStruct
{
char** arr;
int xsize, ysize;
int xstart, ystart;
int xend, yend;
} maze;
/* read in the size, starting and ending positions in the maze */
fscanf (src, "%d %d", &m1.xsize, &m1.ysize);
fscanf (src, "%d %d", &m1.xstart, &m1.ystart);
fscanf (src, "%d %d", &m1.xend, &m1.yend);
/* print them out to verify the input */
printf ("size: %d, %d\n", m1.xsize, m1.ysize);
printf ("start: %d, %d\n", m1.xstart, m1.ystart);
printf ("end: %d, %d\n\n", m1.xend, m1.yend);
//allocating memory for 2d char array
m1.arr = (char**)malloc(m1.xsize+2 * sizeof(char*));
for(i = 0; i < m1.xsize+2; i++)
m1.arr[i] = (char*)malloc(m1.ysize+2);
/* initialize the maze to empty */
for (i = 0; i < m1.xsize+2; i++) <---- when i = 6 it seg faults
for (j = 0; j < m1.ysize+2; j++)
m1.arr[i][j] = '.';
Am I not allocating enough memory or what am I doing wrong?
Your expression:
m1.xsize + 2 * sizeof(char*)
is equivalent to:
(m1.xsize) + (2 * sizeof(char*))
due to precedence of operators, which is not what you want. You need to instead use:
(m1.xsize + 2) * sizeof(char*)
By way of example, let's say you have m1.xsize set to 20 and your pointer size is four bytes. Hence you need space for 22 pointers, which is 88 bytes. The expression m1.xsize + 2 * sizeof(char*) gives you 20 plus double the size of a pointer, totaling 28 bytes, nowhere near enough for what you want to do.
As an aside, you should also stop casting the return value of malloc() since it can hide certain subtle errors. C is perfectly capable of implicitly casting the void* returned from malloc() into any other pointer type.