Free dynamic memory with free() [duplicate] - c

This question already has an answer here:
free 2d array in c
(1 answer)
Closed 5 years ago.
#include <stdlib.h>
#include <stdio.h>
int main() {
char **last_names;
// last_names has been assigned a char * array of length 4. Each element of the array has
// been assigned a char array of length 20.
//
// All of these memory has been allocated on the heap.
// Free all of the allocated memory (hint: 5 total arrays).
return 0;
}
I know the free() method and this is my approach;
free(*last_names);
free(last_names);
but it's not true. Any help will be appreciated

Guessing from your description of the code, your memory allocation would be:
last_names = malloc(4 * sizeof(char*));
for (int i = 0; i < 4; i++)
last_names[i] = malloc(20 * sizeof(char));
So deallocation should be done as follows:
for (int i = 0; i < 4; i++)
free(last_names[i]);
free(last_names);

Related

Segmentation fault when using sprintf in dynamically allocated array

I am converting integers to strings and adding them to a dynamically allocated array. The problem is that it is causing a segfault. I don't understand why it is happening.
#include <stdio.h>
#include <stdlib.h>
int main() {
char *x = malloc(10 * sizeof(char));
x[0] = malloc(10 * sizeof(char));
sprintf(x[0],"%d",10);
for(int i = 0; i < 10;i++){
free(x[i]);
}
free(x);
return 0;
}
To allocate an array whose elements are char*, the pointer to point the array should be char**, not char*.
Also you mustn't use values in buffer allocated via malloc() and not initiaized. The values are indeterminate and using them invokes undefined behavior.
#include <stdio.h>
#include <stdlib.h>
int main() {
/* correct type here (both variable and allocation size) */
char **x = malloc(10 * sizeof(char*));
x[0] = malloc(10 * sizeof(char));
sprintf(x[0],"%d",10);
/* initialize the other elements to pass to free() */
for (int i = 1; i < 10; i++) x[i] = NULL;
for(int i = 0; i < 10;i++){
free(x[i]);
}
free(x);
return 0;
}
If you want a dynamic allocated array of strings, you should declare your variable x as a pointer to an array of e.g. 32 chars. The you can allocate/deallocate an array of these using a single malloc and likewise a single free.
Like:
#define NUM_STRINGS 10
#define STRING_SIZE 32
int main() {
// declare x as a pointer to an array of STRING_SIZE chars
char (*x)[STRING_SIZE];
// Allocate space for NUM_STRINGS of the above array, i.e.
// allocate an array with NUM_STRINGS arrays of STRING_SIZE chars
x = malloc(NUM_STRINGS * sizeof *x);
if (x)
{
for (int i = 0; i < NUM_STRINGS; ++i)
{
sprintf(x[i], "%d", 10 + i);
}
for (int i = 0; i < NUM_STRINGS; ++i)
{
puts(x[i]);
}
free(x);
}
return 0;
}
Output:
10
11
12
13
14
15
16
17
18
19
The best way to determine the amount of memory to be used with malloc is this:
#include <stdio.h>
#include <stdlib.h>
#define N_STRINGS 10
#define STRING_SZ 10
int main() {
// if you use *x (the deferred subexpression) the compiler can calculate its
// sizeof easily, and no need to use a constant or something that has to be
// revised if you change the type of x. Also, calloc will give instead N_STRINGS
// pointers already initialized to NULL.
char **x = calloc(N_STRINGS, sizeof *x);
// to be able to free(x[i]) for all i, you need to initialize all pointers,
// and not only the first one.
int i; // I prefer this, instead of for(int i..., which is more portable with legacy code.
for (i = 0; i < N_STRINGS; i++) {
// char is warranted to be sizeof 1, you don't need to specify but the
// number of chars you want for each character array.
x[i] = malloc(STRING_SZ); // remember only STRING_SZ chars you have, so...
// better to use snprintf(), instead.
snprintf(x[i], // the buffer pointer
STRING_SZ, // the buffer size (STRING_SZ chars, incl. the final null char)
"%d", // the format string
10); // initialize all strings to the string "10" ???
}
// upto here we have made N_STRINGS + 1 calls to malloc...
// you should do something here to check that the allocations went fine, like
// printing the values or do some work on the strings, but that's up to you.
// now, everything should be fine for free() to work.
for(int i = 0; i < N_STRINGS; i++){
free(x[i]);
}
free(x); // ... and this is the N_STRINGS + 1 call to free.
return 0;
}
Check always that the number of free calls executed by your program has to be the same of the malloc calls you have made (before). A free call must free the memory allocated by one (and only one) call to malloc. You cannot free something that has not been acquired by malloc() (or calloc()) directly or indirectly. The same as it is bad use (but not necessary an error) to do a malloc that is not freed before the program ends (this is not true in non-hosted environments, e.g. embedded programs, in which the operating system doesn't deallocate the memory used by a program when it finishes, although)
By the way, the reason of your segmentation fault is precisely that you have made only two calls to malloc(), but you made 11 calls to free(). free() tries to free memory that malloc() has not allocated, or even worse, you don't own. Anyway, this drives you to Undefined Behaviour, which is something you don't desire in a program. In this case, you got a program crash.

Decreasing realloc [duplicate]

This question already has answers here:
Using realloc to shrink the allocated memory
(5 answers)
Can I assume that calling realloc with a smaller size will free the remainder? [duplicate]
(5 answers)
what will realloc do to the old pointer [duplicate]
(6 answers)
Closed 2 years ago.
I have a few questions about understanding
realloc behavior.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *str;
/* Initial memory allocation */
str = malloc(5 * sizeof(int));
*str = 1;
*(str + 1) = 2;
*(str + 2) = 3;
*(str + 3) = 4;
*(str + 4) = 5;
/* Reallocating memory */
int i, j;
for (i = 5; i > 0; i--) {
str = realloc(str, i * sizeof(int));
for (j = 0; j < i; j++) {
printf("%d", *(str + j));
}
printf("\n");
}
free(str);
return(0);
}
In this code example, can I be sure that a smaller realloc will drop the highest number?
Is the realloc is only freeing the last memory and keeping the same address in str? Or may the address change even though it's getting smaller and for sure have space in the current place?
Yes. If you have a memory block p of size N and you do realloc(p, M), then (assuming realloc succeeds), the result will contain the first min(N, M) bytes from p.
The address can change, even if the new size is smaller than the old one. realloc simply makes no guarantees about this case (it can even fail).

Size of matrix not evaluating correctly [duplicate]

This question already has answers here:
Using sizeof with a dynamically allocated array
(5 answers)
Closed 7 years ago.
I'm working on a C program that involves generating adjacency matrices of random graphs. Here is a snippet of the source code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "test.h"
int main()
{
int **A = create_matrix(4, 3);
destory_matrix(A);
return 0;
}
int** create_matrix(int size, int seed)
{
// Allocate space for matrix
int **A = malloc(size * size * sizeof(int));
for (int r = 0; r < size; r++) {
A[r] = malloc(size * sizeof(int));
}
// Fill entries
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
A[i][j] = seed * (i + 1) * (j + 1);
}
}
return A;
}
void destory_matrix(int **A)
{
int size = sizeof(A[0]) / sizeof(int);
for (int r = 0; r < size; r++) {
free(A[r])
}
free(A);
}
This portion of the code is responsible for creating the matrix (the create_matrix() function) and free'ing memory (destroy_matrix()). I'm looking at destroy_matrix(), and noticed that when a 4x4 matrix is passed in, the variable size evaluated to 2, rather than 4. Could anyone explain why this happens?
I think you have a basic misunderstanding of the sizeof operator. It can't, in general, be used to get the size of dynamically allocated compound objects. The sizeof operator returns to you the size based on the type of the operand. In your case, the type of the operand is int *. I guess you are running on a 64 bit system. So the sizeof any pointer is 8. Hence your size variable will always be 2 no matter the size of your matrix.
The sizeof operator applied to a pointer returns the size of the pointer type, not the size of any allocated memory it happens to point to.
This is one of the key differences between an array type and a pointer type in C (note: arrays can decay to pointers). sizeof applied to an statically specified array type (e.g. int foo[n];) will get you the size of the array in bytes.
Since your word size is probably 8 bytes (64-bit), the size of a pointer will be 8 bytes, and if sizeof(int) is 4 bytes (32-bits), you have 8 / 4 = 2;
You need to consider some other way to store the dimensions of your matrices if you need runtime-sized heap-allocated matrices, e.g. a struct that stores the dimensions and a pointer to the allocated memory. It would be better to avoid possible heap-fragmentation altogether, though.
Try this if you have C99:
int n = 4, m = 5;
int (*A)[n] = malloc(m * sizeof A[0]));
free(A);
This allocates an m length array of int[n] as a single block, so you can do size_t n = sizeof(A)/sizeof(A[0]); to get one dimension(n) but you'll need to store m if you want to iterate correctly.

Read strings from console [duplicate]

This question already has answers here:
How to read string from keyboard using C?
(6 answers)
Closed 8 years ago.
I wanna write a program with an array of pointers to char where I store strings read from the console in it. A string is determined by \n. Any ideas how I can do this?
Code with mix of pseudocode so far:
char** arr;
arr = malloc(sizeof(char*) * 5);
arr = malloc(sizeof(char) * 10);
while (No \n read) {
// Store the string in the array
}
I really have no clue how to do this.
#include <stdio.h>
#include <stdlib.h>
int main(){
int i;
char **arr;
arr = malloc(sizeof(char*) * 5);//for 5 string
for(i=0;i<5;++i){
arr[i] = malloc(sizeof(char) * 10);//reserved storage space length 9
scanf("%9[^\n]%*c", arr[i]);//Read until \n, and discard \n
}
printf("\n");
//check print and free
for(i=0;i<5;++i){
puts(arr[i]);
free(arr[i]);
}
free(arr);
return 0;
}
int i, n;
char **arr;
arr = malloc(sizeof(char*) * 5);
for(i=0;i<5;++i){
arr[i] = malloc(sizeof(char) * 10);
}
i=0;
while(i<5 && 1==scanf("%9[^\n]%*c", arr[i]))
++i;
n = i;
printf("\n");
//check print
for(i=0;i<n;++i){
puts(arr[i]);
}
//deallocate
for(i=0;i<5;++i)
free(arr[i]);
free(arr);
You can use this one.
Creating the new char variable and allocate the memory for that. Then get the input like this.
p=(char *)malloc(100);
while ( (*p=getchar())!='\n')p++;
*arr[0]=p;
If you want to create the multiple lines then allocate the memory for that char variable dynamically then store that in the array of pointers.

Allocating array of struct pointers? [duplicate]

This question already has answers here:
malloc an array of struct pointers
(4 answers)
Closed 8 years ago.
I couldn't find answer of the exact question, since the condition is a bit more specific:
How can i allocate array of struct pointers.
typedef struct COORDS
{
int xp;
int yp;
} coord;
coord** xy;
i want to allocate it like: xy[500][460] But it returns invalid memory error when accessing them.
coord** new = malloc (500 * sizeof (coord*));
int idx = 0;
for(; idx < 500; ++idx)
new [idx] = malloc (460 * sizeof (coord));
Static allocation:
coord xy[500][460];
Dynamic allocation:
coord** xy = (coord**)malloc(sizeof(coord*)*500);
for (int i=0; i<500; i++)
xy[i] = (coord*)malloc(sizeof(coord)*460);
// and at a later point in the execution of your program
for (int i=0; i<500; i++)
free(xy[i]);
free(xy);

Resources