#include <stdio.h>
#include <stdlib.h>
char **Names;
int size = 2; //Minimum size for 2D array
void main() {
int i;
Names = (char **)malloc(size * sizeof(char *)); // First initaliaion of 2D array in heap
for (i = 0; i < size; i++)
Names[i] = (char *)malloc(20 * sizeof(char));
printf("\nenter");
for (i = 0; i < size; i++)
scanf("%s", Names[i]);
while (1) {
size++;
Names = (char **)realloc(Names, size * sizeof(char *)); //Dynamic allocation of 2D aray
for (i = 0; i < size; i++)
Names[i] = (char *)realloc(Names[i], 20 * sizeof(char));
i = size - 1;
printf("\nenter");
scanf("%s", Names[i]);
for (i = 0; i < size; i++)
printf("\n%s", Names[i]);
}
}
It doesn't crash immediately it depends on the "size" I initialized.
It crashes after 5 allocations for me.
I tried adding free function but it did not seem to help.
After this memory reallocation
size ++;
Names= (char**)realloc(Names,size*sizeof(char *));
the last pointer pf the array of pointers has an indeterminate value because it was not initialized.
As a result the call of realloc for the last pointer in this loop
for (i=0; i<size; i++)
Names[i] = (char*)realloc(Names[i],20*sizeof(char));
invokes undefined behavior.
Before executing the loop you need to initialize the last pointer at least like
Names[size-1] = NULL;
In fact there is no sense to use the for loop because what you need is to allocate memory for the newly added pointer. The allocated memory pointed to by the early created pointers is not being changed in size.
So instead of
for (i=0; i<size; i++)
Names[i] = (char*)realloc(Names[i],20*sizeof(char));
you could just write
Names[size-1] = malloc( 20 * sizeof( char ) );
Pay attention to as you have an infinite loop then the memory reallocation sooner or later can fail.
Also according to the C Standard the function main without parameters shall be declared like
int main( void )
Related
I am trying to read and print using struct pointer which has pointer members. So I am trying to read and print array of double struct pointers.
I tried the folowing but it is giving me error saying "Access violation writing location (somewhere in memory)"
How can I allocate memory dynamically for this?
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <stdio.h>
#include<string.h>
#include <stdlib.h>
typedef struct template{
char *name;
int *birthdate;
int *phoneNum;
} detailsOf;
void inputValue(detailsOf **person, int maxSize);
int main() {
detailsOf **person;
int maxSize = 0, menu = 0;
printf("Max:");
scanf("%d", &maxSize);
person = (detailsOf **)malloc(maxSize * sizeof(detailsOf **));
if (person == NULL) {
printf("Failed to allocate");
exit(0);
}
for (int i = 0; i < maxSize; i++) {
person[i]->name = (char *)calloc(21, sizeof(char ));
person[i]->birthdate = (int *)calloc(8, sizeof(int ));
person[i]->phoneNum = (int *)calloc(16, sizeof(int ));
}
inputValue(person, maxSize);
for (int i = 0; i < maxSize; i++) {
free(person[i]);
for (int j = 0; j < 21; j++) {
free(person[i]->name[j]);
}
for (int j = 0; j < 15; j++) {
free(person[i]->phoneNum[j]);
}
for (int j = 0; j < 8; j++) {
free(person[i]->birthdate[j]);
}
}
return 0;
}
void inputValue(detailsOf **person, int maxSize) {
for (int i = 0; i < maxSize; i++) {
printf("Name of %d", i + 1);
scanf("%s", person[i]->name);
for (int j = 0; j < 8; j++) {
printf("Birth %d:", i + 1);
scanf("%d", person[i]->birthdate[j]);
}
for (int k = 0; k < 8; k++) {
printf("Phone %d:", i + 1);
scanf("%d", person[i]->phoneNum[k]);
}
}
printf("SUCCESS\n");
}
person = (detailsOf **)malloc(maxSize * sizeof(detailsOf **));
should be
person = malloc(maxSize * sizeof(detailsOf *));
Then, this allocated memory to hold pointers to detailsOf but you never allocate memory for each detailsOf
for(int i=0; i<maxSize; i++)
{
person[i]=malloc(sizeof(detailsOf));
}
Also your freeing of memory should be
for (int i = 0; i < maxSize; i++)
{
free(person[i]->name);
free(person[i]->phoneNum);
free(person[i]->birthdate);
free(person[i]);
}
free(person);
Remember while freeing just match your free calls with malloc calls.
Rule is simple -- a pointer is uninitialized until it has had a valid address assigned to it, or memory has been allocated within which to store things and the starting address for the new block of memory assigned to it.
You allocate maxSize pointers for person, but then fail to allocate a struct for each person[i] before allocating for name, etc..
So you must allocate a struct, e.g. pointer[i] = malloc (sizeof *pointer[i]) before attempting to allocate person[i]->name = calloc(21, sizeof(char ));, ...
Also note, if you allocate based on the size of the derefernced pointer -- you will never get your allocation wrong, (your allocation of person is only correct as the result of happy-accident), instead, e.g.
person = malloc (maxSize * sizeof *person);
...
person[i] = malloc (sizeof *person[i]);
(and note a [] or -> counts as a dereference)
person[i]->name = calloc (21, sizeof *person[i]->name);
There is no need to cast the return of malloc, it is unnecessary. See: Do I cast the result of malloc?
person = (detailsOf **)malloc(maxSize * sizeof(detailsOf **));
This allocates an array of double pointers to type detailsOf with array size as maxSize.
sizeof(detailsOf**) is the size of an address, it does not give you the size of your user-defined datatype detailsOf.
Also, double pointer means, it is an address location which will store the address of another pointer which points to the memory location of detailsOf
/* if you want to use double pointer then */
detailsOf **dptr; // two dimensional array of detailsOf */
detailsOf *sptr; /* one dimentional array of detailsOf */
/* This allocates the memory for storing 3 detailsOf struct data */
sptr = malloc(3 * sizeof(detailsOf));
dptr = &sptr;
/* Now to access double ptr */
for (int i = 0; i < 3; ++i) {
dptr[0][i].birthdate = malloc(3 * sizeof(int));
}
for (int i = 0; i < 3; ++i) {
dptr[0][i].birthdate[0] = i;
dptr[0][i].birthdate[1] = i + 10;
dptr[0][i].birthdate[2] = i + 1990;
}
for (int i = 0; i < 3; ++i) {
printf("%d\\", dptr[0][i].birthdate[0]);
printf("%d\\", dptr[0][i].birthdate[1]);
printf("%d\n", dptr[0][i].birthdate[2]);
}
/* Not to free the double pointer,
* you have to free the inner pointer first then the outer pointers
* Easy to remember is to free in reverse order of your allocation order
*/
for (int i = 0; i < 3; ++i) {
free(dptr[0][i].birthdate);
free(dptr[0]);
/* free(dptr); this is not needed in this example because
* dptr is pointer to address of a local variable,
* but if it points to address of another array of detailOf*
* then this free is needed
*/
}
In your case, you have just an array of pointer and not an array of double pointers.
For example, I have this C code:
int len = 100;
int i;
// arr is pointer-to-pointer 2d array of char
char **arr = malloc(len * sizeof(char*));
for (i = 0; i < len; i++)
{
// Allocate the sub-pointer
arr[i] = malloc(len * sizeof(char));
...
}
...
// Is this part necessary?
for (i = 0; i < len; i++)
{
// Freeing the sub-pointer
free(arr[i]);
}
// Shrink the arr's size from 100 to 50
char** temp = realloc(arr, 50 * sizeof(char*));
...
Before to do realloc for arr to shrink its size (from 100 to 50), is it necessary to free the arr's sub-pointer?
for (i = 0; i < len; i++)
{
free(arr[i]);
}
Yes, you have to free all pointers if the reallocated array will have size that is less than the original size. For example
for (i = 50; i < len; i++)
{
free(arr[i]);
}
char** temp = realloc(arr, 50 * sizeof(char*));
C does not have destructors so you have manually to free all objects pointed to by the removed elements. Otherwise there will be memory leaks.
I'm trying to run this program where a character array is created and allocated memory dynamically. Later the array elements are populated with the string "hello" for 10 consecutive locations. The values are assigned to the string elements using strdup() function call.
Once all the elements are assigned the elements are freed up in the while loop.When I run the program in the Visual Studio, the program crashes after the last pointer to the char array is freed. I believe the termination condition for the while loop is correct. But I'm not able to identify what exactly is causing the issue.
Code:
char **p;
int i;
p = malloc(10 * sizeof(char *));
for (i = 0; i < 10; i++) {
p[i] = strdup(“hello”);
}
while (*p) {
free(*p++);
}
If you want very much to use your while loop then you should write the code the following way
char **p;
int i;
p = malloc(11 * sizeof(char *));
for (i = 0; i < 10; i++) {
p[i] = strdup(“hello”);
}
p[i] = NULL;
while (*p) {
free(*p++);
}
Take into account that you need also to free the initial value of p itself. So the correct code with the while loop could look like
char **p;
int i;
p = malloc(11 * sizeof(char *));
for (i = 0; i < 10; i++) {
p[i] = strdup(“hello”);
}
p[i] = NULL;
char **q = p;
while (*q) {
free(*q++);
}
free( p );
Accessing values outside of array bound, means un authorized memory access. So only,You got crashes at end because of p++ . So try like this.
i=0;
while(i<10)
{
free(p[i]);
i++;
}
You should be iterating over ten elements, not until the non-existent sentinel value (NULL):
for (i = 0; i < 10; i++) {
free(p[i]);
}
Your current code dereferences p[10], which is outside the array bounds and therefore triggers undefined behaviour.
the program is supposed to compare the strings and place them in alphabetical order, but the final printf statement prints garbage...where am i going wrong here?
i have used an array of pointers to strings and declared them in the begining, i have even tried using temp as an array rather than pointer stil doesnt quite work
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int j;
int i;
char *temp;
char *string[5] = {"ibrahim","laura","peter","degea"};
for ( i = 0; i< 4;i++)
printf("%s\n", string[i]); //allocating memory
for( i = 0; i< 10 ;i++)
string[i] = (char*)malloc (30 * sizeof(char));
temp = (char*)malloc(30*sizeof(char));
for ( i=0; i< 3; i++)
for(j =i+1; j<4; j++)
{
if(strcmp(string[i], string[j]) > 0)
{
strcpy(temp, string[i]);
strcpy(string[i], string[j]);
strcpy(string[j], temp);
}
}
for (i = 0; i< 4; i++)
{
printf("%s\n",string[i]);
puts("\n");
}
free(string);
free(temp);
return 0;
}
string[i] = (char*)malloc (30 * sizeof(char));
This is overwriting the existing initialized values.
EDIT
for( i = 0; i< 10 ;i++)
temp = (char*)malloc(30*sizeof(char));
WHAT? you are allocating memory over and over 10 times on a single pointer?
EDIT 2:
The original post is lost (read Edited). By the time you are reading this answer, both Mr. Jonathan Leffler and this poster migh look like absolute fools in this world.
The code originally destroyed its data array (by allocating new pointers). Now it seems to throw memory away by allocating temp four times (but Jeevan's edit reinstates the old code in indented form). The old code allocated space for strings but never initialized them (having thrown away the value that was in the array beforehand).
NB: any commentary on the code could easily be invalid by the time you're reading the commentary — the code in the question could have changed.
for (i = 0; i < 10; i++)
string[i] = malloc(30);
This code tramples out of the bounds of the string array (dimension is 5). It also loses the data originally in the array.
You need to use strcmp() to compare the strings, but you simply need to swap pointers rather than using strcpy() at all.
The comment // allocating memory beside a printf() statement is misleading, too.
This stands a chance of working. Note that there is no memory allocation:
#include <stdio.h>
#include <string.h>
int main(void)
{
int j;
int i;
char *string[] = { "ibrahim", "laura", "peter", "degea" };
for (i = 0; i < 4; i++)
printf("%s\n", string[i]);
for (i = 0; i < 3; i++)
{
for (j = i+1; j < 4; j++)
{
if (strcmp(string[i], string[j]) > 0)
{
char *temp = string[i];
string[i] = string[j];
string[j] = temp;
}
}
}
for (i = 0; i < 4; i++)
printf("%s\n",string[i]);
return 0;
}
Output:
ibrahim
laura
peter
degea
degea
ibrahim
laura
peter
Comment: don't try sorting thousands of strings using this sort algorithm.
You are overwriting the existing string array contents with malloc, that too 10 times.
Please use braces in your code for better understanding
for( i = 0; i< 10 ;i++)
string[i] = (char*)malloc (30 * sizeof(char));
temp = (char*)malloc(30*sizeof(char));
can be written as
for( i = 0; i< 10 ;i++) // why to allocate memory ten times, that too overwriting
{
string[i] = (char*)malloc (30 * sizeof(char));
}
temp = (char*)malloc(30*sizeof(char));
when you declare :
char *string[5] = {
"ibrahim",
"laura",
"peter",
"degea" };
the pointer *string[0] to *string[3] allocated to a address in the memory, where will stored the init values "ibrahim","laura"...
when you use malloc function for the pointer string[i] = (char*)malloc (30 * sizeof(char));
the pointer *string[0] to *string[4] will be allocated to another address in the memory. so the value at these address are different from that you initialized (ibrahim,laura).
you should use static array instead dynamic as below
char temp;
char string[5] = {
"ibrahim",
"laura",
"peter",
"degea" };
remove all the malloc, free function.
I have a project where I create a 2D char array that stores words, with the option to add more words, and then resize the array when necessary. I'm getting a variety of errors as I try to play with it and fix it so now I think I need some extra eyes on my code. I'm specifically looking for anything that obviously stands out as an incorrect or troublesome way of allocating memory or initializing an array.
The error I am getting specific to this code says "free(): invalid pointer" and leads to a SIGABRT. Below is my code.
Here is my resize function.
char ** resize_array(char **array)
{
int i;
char** tmp = malloc(2 * sizeof(*array));
int j;
for(j = 0; j < (2 * sizeof(*array)); j++)
tmp[j] = malloc(2 * sizeof(*array));
for(i = 0; i < (sizeof *words); i++)
{
strcpy(tmp[i], words[i]);
}
for(i = 0; words[i] != NULL; i++)
free(words[i]);
free(words);
return tmp;
}
Here is my resize function being implemented
int len;
len = (sizeof words);
if(upperbound > len) //upperbound keeps track of the word count
//and resizes the array
{
char **tmp = resize_array((char **) words);
int i;
for(i = 0; i <= upperbound; i++)
strcpy(words[i], tmp[i]);
}
And finally here is the "words" array as it is initially initialized.
char words[14][50];
I'm using VI and running everything on Ubuntu just fyi. Thanks in advance for everyones help!
Inside the resize_array function, you can't determine the previous size of the array using only a pointer to it.
The call to malloc
malloc(2 * sizeof(*array))
requests an allocation twice the size of a pointer to a char (only 16 bytes on a 64bit machine).
This is the first problem you need to fix.