How to allocate a dynamic array of struct - c

i have a problem with the allocation of a dynamic struct array.
The struct is composed of a char* field, that is another dynamic array of char. After i allocate all arrays, windows block the program when i try to modifty a struct content. Code:
typedef struct
{
char *cod;
}code;
void create_cod(code *singleCode,int codeLength);
void create_codes(code *codes, int codesNumber, int codeLength);
int main()
{
int codesNumber=4, codeLength=10;
code *codes;
create_codes(codes, codesNumber, codeLength);
codes->cod = "abcd"; /*Windows block the program here*/
}
void create_cod(code *singleCode,int codeLength)
{
singleCode->cod = (char*)malloc(codeLength*sizeof(char));
return;
}
void create_codes(code *codes, int codesNumber, int codeLength)
{
codes= (code*)malloc(codesNumber*sizeof(code));
int i=0;
while(i<codesNumber)
{
create_cod(codes+i,codeLength);
i++;
}
return;
}

Related

Dynamic Memory allocation of array inside structure in C

I'm doing dining-philosopher problem in C for assignment. And got stuck very begining of my code.
I decided each philosopher to be structure, and forks to be int array.
But I can't use global variable in this assignment.
So, I have to include shared variable in philosopher structure to pass them for arguments of thread routine.
Here is my problem - how to include int array in structure if I can't know proper size of them when initializing?
My plan is just include pointer variable in structure then allocate array's address using &.
But It doesn't work :
#include <stdlib.h>
/* inside structure*/
typedef struct s_share {
int **forks;
} t_share;
/* outside structure */
typedef struct s_philo {
t_share *share;
} t_philo;
int main(void)
{
t_philo *philo;
int *forks;
int i;
i = 0;
/* malloc structure arrary philo, size = 10 */
philo = (t_philo *)malloc(sizeof(t_philo) * 10);
/* malloc int arrary forks, size = 100 */
forks = (int *)malloc(sizeof(int) * 100);
while (i < 10)
{
philo[i].share->forks = &forks; //error
i++;
}
}
Output : segmentation fault
I tested share->forks size like this :
printf("size of forks : %ld\n", sizeof(philo->share->forks));
Output was 8.
It's enough size to store int * pointer.
Through this I know It's not the memory allocation problem.
Then what is problem? Can someone check this for me?
Edit :
When I try to malloc directly philo->share->forks, I got same error.
typedef struct s_share {
int *forks;
} t_share;
typedef struct s_philo {
t_share *share;
} t_philo;
int main(void)
{
t_philo *philo;
int *forks;
int i;
i = 0;
philo = (t_philo *)malloc(sizeof(t_philo) * 10);
while (i < 10)
{
philo[i].share->forks = (int *)malloc(sizeof(int) * 100); //error
i++;
}
}
I thought it's because when philo initialized, sizeof operator calculated forks's memroy to be 8 - which required for pointer.
Is there something wrong?
Edit 2 :
To clear my question,
It's easy to solve this problem, if I write size of array in structure definition.
typedef struct s_share {
int forks[100];
} t_share;
typedef struct s_philo {
t_share *share;
} t_philo;
but according to my assignmet I have to get philosopher's number from cmd. So I can't do that.
Above is simple version of my origin code
Sorry, Edit 2 is wrong :
typedef struct s_share {
int forks[100];
} t_share;
typedef struct s_philo {
t_share *share;
} t_philo;
int main(void)
{
t_philo *philo;
t_share *share;
int *forks;
int i;
i = 0;
philo = (t_philo *)malloc(sizeof(t_philo) * 10);
while (i < 10)
{
philo[i].share->forks[i] = 1;
i++;
}
}
Output
zsh: segmentation fault ./a.out
I still got segfault when I write array size in struct definition.
I used calloc to initialize all member in my struct but same error occurs :
typedef struct s_share {
int **forks;
} t_share;
typedef struct s_philo {
t_share *share;
} t_philo;
int main(void)
{
t_philo *philo;
t_share *share;
int *forks;
int i;
i = 0;
philo = (t_philo *)calloc(10, sizeof(t_philo));
forks = (int *)calloc(100, sizeof(int));
while (i < 10)
{
philo[i].share->forks = &forks; //error
i++;
}
}
Edit 4:
I finally found error. It's because I didn't malloc 'share' struct in philo struct
typedef struct s_share {
int **forks;
} t_share;
typedef struct s_philo {
t_share *share;
} t_philo;
int main(void)
{
t_philo *philo;
int *forks;
int i;
i = 0;
philo = (t_philo *)malloc(sizeof(t_philo) * 10);
forks = (int *)malloc(sizeof(int) * 100);
while (i < 10)
{
philo[i].share = (t_share *)malloc(sizeof(t_share)); //here
philo[i].share.forks = &forks;
i++;
}
}
That one line -allocating struct share- solved problem.
Or, I can modify philo struct definition like this :
typedef struct s_philo {
t_share share; //not pointer, just struct
} t_philo;
In this way, I can automatically malloc struct share.
I got confused in this point. Thanks for helping!
this line
philo[i].share->forks
Is dereferencing the pointer 'share' which is not set. You called malloc and did not set any values, so the data inside your allocated buffer is 'garbage' data.
// add begin
t_share* new_share = (t_share*)malloc(sizeof(t_share));
philo[i].share = new_share;
// add end
// don't use &forks
philo[i].share->forks = forks; //error
i++;
// need forks++
forks++;

I want to access a general struct field inside another struct's field in C

I have a struct defined like this:
typedef struct {
char id[20];
char descrizione[250];
char tipoSet[30];
int scatoleDisponibili;
float costo;
} Set;
I have another struct called Complex in which I want a field to store an array of only Set struct IDs.
typedef struct {
char idComplesso[20];
content[10];
int dimLogica;
} complex;
So, I want the content array (of max size 10) to be able to store only the string id from a max of 10 Set.
How could I do this in C?
typedef struct {
char id[20];
char descrizione[250];
char tipoSet[30];
int scatoleDisponibili;
float costo;
} Set;
typedef struct {
char idComplesso[20];
int dimLogica;
size_t nsets;
char *content[];
} complex;
complex *assign(Set *s, size_t nsets)
{
complex *cml = malloc(sizeof(*cml) + nsets * sizeof(cml -> content[0]));
/* allocation check */
cml -> nsets = nsets;
for(size_t i = 0; i < nsets; i++)
{
cml -> content[i] = s[i].id;
}
return cml;
}
You'll have to make the content array be an array of char* and when you create the structure only accept id from a Set struct.
Something like this:
complex* createComplex(Set* sets) {
complex* comp = (complex*)malloc(sizeof(complex));
for (int i=0; i<10; i++) {
comp->content[i] = sets[i].id;
}
return comp;
}
And don't let any other function create the comp struct

two functions (read and display an array) using pointers to structures

I just start to learn pointers to structures and I'm confused.I have to create a type of data ARRAY (which is associated with an array which contains integers.) like a structure which contains: numbers of array's elements and the array's elements stored in a part of memory(heap), dynamically allocated.
So I wrote:
typedef struct ARRAY
{
int nrElem; // number of elements
int *v[100];
};
Now I need to create 2 functions, one for reading an array from keyboard and the second one to display it using the structure I declared.
I tried but I get stuck.
void arrayDisplay(ARRAY *ps)
{
int i;
for(i=0;i<pd->nrElem;++i)
{
printf("%d",)
}
}
void readArray(ARRAY *ps)
{
int i;
for(i=0;i<pd->nrElem;++i)
{
printf("%d",)
scanf("%d",&);
}
}
How to continue?
Instead of an array of pointers int *v[100]; you need an array of ints int v[100]; in your data structure.
See code below:
#include <stdio.h>
#include <stdlib.h>
typedef struct ARRAY
{
int nrElem; // number of elements
int v[100];
} ARRAY;
void arrayDisplay(ARRAY *ps)
{
int i;
for(i=0;i<ps->nrElem;++i)
{
printf("%d\n", ps->v[i]);
}
}
void readArray(ARRAY *ps)
{
int i;
for(i=0;i<ps->nrElem;++i)
{
printf("%d: ", i);
scanf("%d",&ps->v[i]);
}
}
int main()
{
ARRAY a;
a.nrElem = 5;
readArray(&a);
arrayDisplay(&a);
return 0;
}
If you really want to use an array of int pointers you need to allocate the array first. And a different level of redirection for printf and scanf. But I'm not sure why you want to allocate memory for an integer array like this.
typedef struct ARRAY
{
int nrElem; // number of elements
int *v[100];
} ARRAY;
void arrayDisplay(ARRAY *ps)
{
int i;
for(i=0;i<ps->nrElem;++i)
{
printf("%d\n", *ps->v[i]);
}
}
void readArray(ARRAY *ps)
{
int i;
for(i=0;i<ps->nrElem;++i)
{
printf("%d: ", i);
scanf("%d",ps->v[i]);
}
}
int main()
{
ARRAY a;
int i;
a.nrElem = 5;
for(i=0;i<a.nrElem;++i) {
a.v[i] = (int*)malloc(sizeof(a.v[i]));
}
readArray(&a);
arrayDisplay(&a);
return 0;
}

Why updated structure variable not printing

This is my code in which if student marks is greater than 85,scholarship status will be changed to sanctioned, but after updating it is not printing
#include<stdio.h>
#include<string.h>
struct scholor
{
char name[25];
int sem;
int marks;
char status;
};
void sanction(int m, char *s)
{
if(m>85)
{
char p[15]="sanctioned";
char *r;
r=p;
while(*r!='\0')
{
*s=*r;
s++;
r++;
}
*s='\0';
}
}
int main()
{
struct scholor s1;
scanf("%s%d%d%s",&s1.name,&s1.sem,&s1.marks,&s1.status);
sanction(s1.marks,&s1.status);
printf("%s",s1.status);
}
status is a single char but you are storing a string into it, effectively doing out of bounds access (undefined behaviour). Change it to an array and then you'll be able to copy.
struct scholor
{
char name[25];
int sem;
int marks;
char status[128];
};
and adjust the calls and passing (since status is an array now -- its name gets converted into a pointer t its first element when passed to functions):
scanf("%s%d%d%s",s1.name,&s1.sem,&s1.marks,s1.status);
sanction(s1.marks,s1.status);
printf("%s",s1.status);
Other suggestions:
1. Use a standard prototype for main such as: int main(void)
2. You could usr strcpy to copy the string as opposed to doing it yourself.
Your struct should have status as a character array not a character .Moreover when you scanf an array dont write & before because the name itself points to the assdress of the first element.Your corrected program is :
struct scholor
{
char name[25];
int sem;
int marks;
char status[16];
};
void sanction(int m, char *s)
{
if(m>85)
{
char p[15]="sanctioned";
char *r;
r=p;
while(*r!='\0')
{
*s=*r;
s++;
r++;
}
*s='\0';
}
}
int main()
{
struct scholor s1;
scanf("%s%d%d%s",s1.name,&s1.sem,&s1.marks,s1.status);
sanction(s1.marks,s1.status);
printf("%s",s1.status);
}

C - memory management

I just wrote some C code:
#include <stdlib.h>
#include <time.h>
#include <string.h>
typedef struct {
void **data;
time_t lastModified;
} container;
container *container_init() {
container *c = malloc(sizeof(container));
void *data = NULL;
c->data = &data;
c->lastModified = time(NULL);
return c;
}
void *container_getData(container *c) {
void **containerData = c->data;
return *containerData;
}
// only pass manually allocated data that can be free()'d!
void container_setData(container *c, void *data) {
free(container_getData(c));
c->data = &data;
}
void container_free(container *c) {
free(container_getData(c)); // <--- THIS LINE
free(c);
}
int main(int argc, const char *argv[]) {
for (int i = 0; i < 100000000; i++) {
char *data = strdup("Hi, I don't understand pointers!");
container *c = container_init();
container_setData(c, data);
container_free(c);
}
}
My logic was the following: When I call container_setData(), the old data is free()'d and a pointer to the new data is stored. That new data will have to be released at some point. That happens for the last time during the call to container_free().
I have marked a line in the container_free() function. I would have sworn I'd need that line in order to prevent a memory leak. However, I can't use the line ("object beeing freed was not allocated") and there's no memory leak if I delete it. How does the string from my loop ever get released?!
Could someone explain where the error is?
c->data = &data;
stores the address of the pointer data (the argument to your function), not the actual pointer. I.e., you're storing a pointer to a temporary.
You could have built the container structure with just a void *data member.
To explain larsmans answer with code make these changes:
typedef struct {
void *data;
time_t lastModified;
} container;
void *container_getData(container *c) {
return c->data;
}
void container_setData(container *c, void *data) {
free(c->data);
c->data = data;
}
void container_free(container *c) {
free(c->data);
free(c);
}
And other changes too -- this just gets you on the right track.

Resources