free() the reserved data with malloc - c

Hi I have written this Program which create a list of books which is given by the User and i can't free the my_value at the end of program and get a lot of errors . This is my Code
#include <stdio.h>
#include <stdlib.h>
int main(){
int n;
printf("Please Enter the Number of Books:\n");
scanf("%d",&n);
char **array=(char *) malloc((n+1)*sizeof(char *));
for(int i=0;i<n;i++){
array[i] = (char *)malloc(sizeof(char *));
}
for(int i=0;i<n;i++){
char *my_value=(char *) malloc(sizeof(char)*100);
printf("Please Enter the Name of the %dth Book:\n",i+1);
scanf("%s",my_value);
*(array+i)=my_value;
free(my_value);
}
for(int i=0;i<n;i++){
printf("\n The Book Nr.%d is %s \n",i+1,*(array+i));
}
for(int i=0;i<n;i++){
free(array[i]);
}
free(array);
return 0 ;
}

First, in
char **array=(char *) malloc((n+1)*sizeof(char *));
you don't need n+1 pointers since you use only n.
Then, this loop
for(int i=0;i<n;i++){
array[i] = (char *)malloc(sizeof(char *));
}
is unnecessary (and wrong). array[i] is to be overwritten just after.
In the next loop
*(array+i)=my_value; // is array[i] = my_value
free(my_value); // <=== why? remove that line!
you free what you just allocated -- array[i] cannot be used anymore from that point! Lead to undefined behavior.

Related

Creating a 1-D array of strings from user input in C

I was attempting to create an array from user input in C. My code was as follows
#include <stdio.h>
#include <stdlib.h>
char** create_array(int num);
int main(){
char** my_array;
int i;
printf("%s", "Input the size of the array: ");
scanf("%d", &i);
my_array = create_array(i);
for (int m = 0; m < i; m++){
printf("%s\n", (char*)my_array[m]);
}
}
char ** create_array(int num){
char** array = malloc(num * sizeof(char*));
for (int i = 0; i < num; i++) {
char temp[32];
printf("Input element %d of the array: ", i);
scanf("%s", temp);
array[i] = temp;
}
for (int m = 0; m < num; m++){
printf("%s\n", array[m]);
}
printf("end of func\n");
return array;
}
I was having (possibly unrelated?) issues with segmentation faults until I replaced the declaration of temp from char *temp; to char temp[32];. I am not sure of why declaring temp as a char pointer creates the segmentation fault, if that is a simple related answer let me know, if not I will ask in another question.
However, when I run this code, upon inputting
Input the size of the array: 2
Input element 0 of the array: value0
Input element 1 of the array: value1
I get
value1
value1
end of func
Segmentation fault (core dumped)
So to me it seems like temp somehow isn't changing when the for loop executes next iteration. I'm not sure why or how that would ever happen though. I also tried changing
printf("%s\n", my_array[m]);
to
printf("%s\n", (char*)my_array[m]);
but that didn't seem to help either.
Any ideas?
Thanks
I believe this is what you're looking for. The trick is allocate the memory for the strings on the heap. Saving pointers to char temp[32]; is dangerous because it's in automatic storage. As #Spikatrix said in a comment, that memory is not guaranteed to be in a valid state between each iteration of the loop. With the data on the heap, there's a well-defined region of memory set aside and identified by the pointer returned from malloc.
There's also a lot of good reason to not use scanf. As is, your code does not do any bounds checks and can easily overwrite the 32-byte array allocated for each string.
#include <stdio.h>
#include <stdlib.h>
char** create_array(int num);
int main(){
int num_strings;
printf("Input the size of the array: ");
scanf("%d", &num_strings);
printf("\n");
char** my_array = create_array(num_strings);
for (int i = 0; i < num_strings; i++){
printf("%s\n", my_array[i]);
}
for (int i = 0; i < num_strings; i++) {
free(my_array[i]);
}
free(my_array);
}
char** create_array(int num) {
char** array = malloc(num * sizeof(char*));
for (int i = 0; i < num; i++) {
array[i] = malloc(32);
printf("Input element %d of the array: ", i);
scanf("%s", array[i]);
printf("\n");
}
printf("end of func\n");
return array;
}

The number of elements in a pointer as an array

I'm trying to count the number of elements in an array as a pointer as the code followed:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *ptr = (int *) malloc(sizeof(int*));
for(int i=0; i<8; i++)
{
printf("The number: " );
scanf("%d", &ptr[i]);
}
int size = sizeof(ptr)/sizeof(int);
printf("%d\n", size);
return 0;
}
I have tried the syntax for an array size = sizeof(ptr)/sizeof(int);but I got the wrong answer which is 1 for all cases. I don't know how to get the correct answer, which is 8 for this case
Unfortunately, you cannot get the size of an array allocated with malloc (because you are actually getting the size of a pointer). You must always store that somwhere else. Since you always allocate 8 elements, why not make it a static array?
#include <stdio.h>
int main()
{
int arr[8];
for(int i=0; i<8; i++)
{
printf("The number: " );
scanf("%d", &arr[i]);
}
int size = sizeof(arr)/sizeof(int);
printf("%d\n", size);
return 0;
}

sorting strings while using malloc

how can i sort the string without breaking the program? the string input had to be done without the use of gets(fgets , getsc etc.)
int main ()
{
char **pointsarr;
char temp;
printf("insert strings: \n");
scanf("%d",&a);
printf("declare the size of the strings: \n");
pointsarr = malloc(a * sizeof(char*));
for (i=0; i<a; i++)
{
pointsarr[i]= malloc(b* sizeof(char));
}
printf("input strings: \n");
for (i=0; i<a; i++)
{
scanf("%s", pointsarr[i]);
}
printf("the strings on the 2d board: \n");
for (int i=0; i<a; i++)
printf("%s\n",pointsarr[i]);
/* int n= strlen(pointsarr);
for (i=0; i<n-1; i++)
{
for(j=i+1; j<n; j++)
{
if (pointsarr[i]>pointsarr[j])
{
temp=pointsarr[i];
temp=pointsarr[i]; // whats going wrong on this point?
pointsarr[i]=pointsarr[j];
pointsarr[j]=temp;
}
}
}
*/
free(pointsarr);
}
in this if whats going wrong and it dosent return the sorted string?
The easiest way to sort your array is to use the library function qsort().
Sample code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int comparefunc (const void* p1, const void* p2)
{
return strcmp (* (const char **) p1, * (const char **) p2);
}
int main ()
{
int i, a = 4, b = 20;
char **pointsarr = (char **) malloc(a * sizeof(char*));
for (i=0; i<a; i++)
pointsarr[i]= (char *) malloc(b* sizeof(char));
strcpy (pointsarr [0], "qwerty");
strcpy (pointsarr [1], "uiop");
strcpy (pointsarr [2], "asdf");
strcpy (pointsarr [3], "ghjkl");
for (i=0; i<a; i++)
printf("%s\n",pointsarr[i]);
printf("-----\n");
qsort (pointsarr, a, sizeof (char **), comparefunc);
for (i=0; i<a; i++)
printf("%s\n",pointsarr[i]);
}
Output:
qwerty
uiop
asdf
ghjkl
-----
asdf
ghjkl
qwerty
uiop
Live demo
Problem 1: the line int n= strlen(pointsarr); is certainly wrong, as pointsarray is a pointer to an array of strings, not a pointer to a string.
It is also unnecessary, as you already have the length of the array: it's a.
Problem 2: see the comment by #xing

Faulty Dynamic memory allocation for larger values

In the code below, i am taking n as a user input, and depending on its value i have allocated memory to the pointer array (both n and pointer array are a part of a structure). The whole code works well for values of n below 4, anything 4 or beyond, its giving a segmentation fault while inputting values in the pointer array.
I can imagine that it might be because the memory isn't getting allocated but why its only beyond 4 I don't understand
Here is a snippet where the problem is happening.
#include <stdio.h>
#include <stdio_ext.h>
#include <stdlib.h>
// static int n;
typedef struct test_case {
int n;
int *test[];
} testCase;
int maxsc(testCase *test_case_ptr);
int find_maximum(int *ptr, int n);
int main() {
int T;
int x = 0;
int temp;
testCase *test_case_ptr;
printf("T = ");
scanf("%d", &T);
printf("\n");
for (int i = 0; i < T; i++) {
printf("N = ");
scanf("%d", &test_case_ptr->n);
temp = test_case_ptr->n;
printf("\n");
test_case_ptr = (testCase *)malloc(sizeof(struct test_case));
for (int i = 0; i < temp; i++) {
test_case_ptr->test[i] = malloc(sizeof(int *) * test_case_ptr->n);
}
test_case_ptr->n = temp;
// printf("%d\n", test_case_ptr->n);
printf("give values\n");
for (int j = 0; j < test_case_ptr->n; j++) {
for (int k = 0; k < test_case_ptr->n; k++) {
scanf("%d", &test_case_ptr->test[j][k]);
}
}
int max_score = maxsc(test_case_ptr);
printf("\n");
printf("The max_score_%d = %d \n", x++, max_score);
}
}
First, you try to use the test_case_ptr struct before allocating mem for it. Second, when using a flexible array, you need to alloc the mem for it when you malloc the mem for the struct.
scanf("%d", &temp);
// Allocate mem for the struct plus the array
test_case_ptr = malloc(sizeof(struct test_case) + sizeof(int *) * temp);
test_case_ptr->n = temp;
// Allocate each row in the array
for (int i = 0; i < test_case_ptr->n; i++) {
test_case_ptr->test[i] = malloc(sizeof(int) * test_case_ptr->n);
}
// .....

Call a function that receives an array using a pointer

So I've this:
int main()
{
int workers;
printf("How many workers are there?\n");
scanf("%d", &workers);
printf("What are their preferences?\n");
int *pref = malloc(workers * sizeof(int));
if (pref == NULL)
return -1;
fillPreferences(pref, workers);
return 0;
}
I want now to fill the "pref" 2d array in this function:
void fillPreferences(int pref[][], int size)
{
for (int i=0;i<size;i++)
{
for (int j=0;j<size;j++)
{
scanf(" %d", &pref[i][j]);
}
}
}
It doesn't work, probably because I'm using the pointer wrong. How can I use malloc and then call a function and receive the values in the 2d array by doing pref[i][j]? (Note that I'm not looking to do something like scanf(..., &pref+i) or whatever. I need to actually use that 2d array.
Thanks :)
When you write a[i], it is turned into *(a+i). That is, a[i] accesses the memory by a+i address (well, it is a+i*sizeof(element) even).
As such, a[i][j] means *(*(a+i)+j). Two memory accesses. For this to work, your a should be an array of arrays. That is, you need to malloc its elements first and then malloc a memory to hold them.
In your particular case, i doubt you need it. What you need is make it 1D-array (which is it already) and calculate index from your two indices in whatever fashion you wish.
Your pref array is 1D so you can make it in this way:
#include <stdio.h>
#include <stdlib.h>
void fillPreferences(int **pref, int size)
{
int prefNum=0;
for (int i=0;i<size;i++)
{
puts("Number of preferences");
scanf("%d",&prefNum);
pref[i]=malloc(sizeof(int)*prefNum);
puts("Enter preferences");
for(int j=0;j<prefNum;j++){
scanf(" %d", &pref[i][j]);
}
}
}
int main()
{
int workers;
printf("How many workers are there?\n");
scanf("%d", &workers);
printf("What are their preferences?\n");
int **pref = malloc(workers * sizeof(int *));
if (pref == NULL)
return -1;
fillPreferences(pref, workers);
// Show values
printf("%d %d %d",pref[0][0],pref[1][0],pref[2][0]);
return 0;
}
You allocate memory for a 1D array, but the function you have is designed to accept a 2D array and fill it (although the function definition is incorrect and won't compile).
Corrected code:
#include <stdio.h>
#include <stdlib.h>
void fillPreferences(int** pref, int size)
{
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
scanf("%d", &pref[i][j]);
}
}
}
int main()
{
int workers;
printf("How many workers are there?\n");
scanf("%d", &workers);
printf("What are their preferences?\n");
int **pref = malloc(workers * sizeof(int*));
if (pref == NULL)
return -1;
for(int i = 0; i < workers; i++)
{
pref[i] = malloc(workers * sizeof(int));
if(pref[i] == NULL)
{
for(int j = 0; j < i; j++)
free(pref[j]);
free(pref);
return -1;
}
fillPreferences(pref, workers);
/* Don't forget to `free` everything after its use! */
return 0;
}

Resources