Below I have a struct with multiple dynamically allocated char arrays.
It compiles, Valgrind indicates no issues and it functions as anticipated.
Earlier, someone tried to explain to me I may encounter memory issues down the road. Their reasoning was that one of the variables may exceed the contagious memory allocated for the foo instance.
Should I be performing a malloc on foo every time I allocate memory for its variables?
Live Demo
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct foo_t{
char *strA;
char *strB;
char *strC;
int x;
} foo;
int main() {
char *str1 = "Hello World";
char *str2 = "foo";
char *str3 = "Kolmongorov complexity";
foo *point = malloc(sizeof(foo));
point->x = 100000;
point->strA = calloc(strlen(str1)+1, sizeof(char));
point->strB = calloc(strlen(str2)+1, sizeof(char));
point->strC = calloc(strlen(str3)+1, sizeof(char));
strcpy(point->strA, str1);
strcpy(point->strB, str2);
strcpy(point->strC, str3);
free(point->strA);
free(point->strB);
free(point->strC);
free(point);
return 0;
}
In your example, the foo struct doesn't really contains the arrays : it contains pointers to arrays.
When arrays are resized, the size of pointers remains the same, so there's no need to reallocate the foo struct.
Just be aware that resizing an array with realloc may change its memory address, so pointers in foo struct will have to be reassigned according to that.
Their reasoning was that one of the variables may exceed the contagious memory allocated for the foo instance.
That's nonsense, whoever told you as much didn't understand how allocation works. The struct only allocates the pointers, not what they point at. It will have the very same size, always. The pointers may point at memory allocated anywhere, not necessarily even on the heap.
Should I be performing a malloc on foo every time I allocate memory for its variables?
You need to allocate memory for it once, before accessing the pointer members. But in case the data pointed at by the pointer members are changed, then that doesn't affect the struct and it need not get reallocated.
I think memory management is one of the most important topic in C, but it's far more confusing than you may thought at first. This question can be a great entrypoint to illustrate it, so I will try my best to explain it in detail.
First consider the following three C struct definitions:
#define STR_SIZE 16
struct foo_A {
char str1[STR_SIZE];
char str2[STR_SIZE];
};
struct foo_B {
char *str1;
char *str2;
};
struct foo_C {
char str1[STR_SIZE];
char str2[];
};
Note that foo_C is legal, not a typo. What' their difference?
Well, let's consider foo_A and foo_B first. It looks like both of them try to describe and manage two strings. So for memory management, the first question you have to think is where the memory comes from.
In general there are two ways to get the memory, one is "I will allocate it by myself" and the other is "Someone else will allocate it, I just take it and manage". As you might guess, the former in-place style is foo_A, while the latter is foo_B.
More specifically, in C, you will use them in different styles(headers are omitted):
char str1[] = "I'm string A";
char str2[] = "I'm string B";
int main() {
struct foo_A foo_A;
struct foo_B foo_B;
memset(&foo_A, 0, sizeof(struct foo_A));
memset(&foo_B, 0, sizeof(struct foo_B));
foo_B.str1 = (char *)malloc(sizeof(str1));
foo_B.str2 = (char *)malloc(sizeof(str2));
strcpy(foo_A.str1, str1);
strcpy(foo_A.str2, str2);
strcpy(foo_B.str1, str1);
strcpy(foo_B.str2, str2);
/*
safely manipulate foo_B strings
...
*/
free(foo_B.str1);
free(foo_B.str2);
}
As you see, compared to foo_A's out-of-box usage, we have to deal with memory allocation before access foo_B's strings. If you omit these steps, the program just crashes.
What causes such difference, more formally, lies that foo_A itself contains the resource it is to manage, while foo_B doesn't. foo_B just contains a handle to the resource it is to manage, and before you use foo_B, you have to first do have a resource, and attach it to the handle. Of course the allocation/release of such resource is not the job of foo_B.
Before jump back to your reallocation confusion, another problem remains to deal with: management of management struct itself.
As you see, the code above doesn't allocate/free struct foo_A or struct foo_B besides some memset erasing. This is not always the case, while I choose this way to make the code clear and avoid introducing this problem too early.
Now consider the following two alternatives:
/*
alternative_1.c
str1, str2 remain the same
*/
struct foo_A foo_A;
struct foo_B foo_B;
int main() {
foo_B.str1 = (char *)malloc(sizeof(str1));
foo_B.str2 = (char *)malloc(sizeof(str2));
strcpy(foo_A.str1, str1);
strcpy(foo_A.str2, str2);
strcpy(foo_B.str1, str1);
strcpy(foo_B.str2, str2);
/*
safely manipulate foo_B strings
...
*/
free(foo_B.str1);
free(foo_B.str2);
}
/*
alternative_2.c
str1, str2 remain the same
*/
int main() {
struct foo_A *foo_A = (struct foo_A *)malloc(sizeof(struct foo_A));
struct foo_B *foo_B = (struct foo_B *)malloc(sizeof(struct foo_B));
memset(foo_A, 0, sizeof(struct foo_A));
memset(foo_B, 0, sizeof(struct foo_B));
foo_B->str1 = (char *)malloc(sizeof(str1));
foo_B->str2 = (char *)malloc(sizeof(str2));
strcpy(foo_A->str1, str1);
strcpy(foo_A->str2, str2);
strcpy(foo_B->str1, str1);
strcpy(foo_B->str2, str2);
/*
safely manipulate foo_B strings
...
*/
/* free managed string */
free(foo_B->str1);
free(foo_B->str2);
/* free management struct itself */
free(foo_A)
free(foo_B)
}
As you see, the way we get foo_A and foo_B varies. In the very first example, we define them within function body, which means they are automatically allocated on stack(case 1). In alternative_1.c, we define them as static variable whose space is allocated at compile time(case 2), while in alternative_2.c they are allocated on heap by malloc(case 3).
No matter how you get foo_A and foo_B, the key point is the same as before: you have to first do get a it. And manage them. You can free them manually(case 3), or relying on automatic varialbe reclaim(case 1), or at process exiting(case 2).
After all these discussions, you may find that the management of resource(e.g. string) and the management of management resource(e.g. foo_A or foo_B) are independent. So if your resouce changed like, just as you say, the string is resized by reallocation, you don't have to reallocate your management resource(i.e. foo_X). That' s it.
Remember there is still a struct foo_C? Before talking about it I want to first discuss why you may choose struct foo_A or struct foo_B.
It turns out that foo_A cannot manage variable-length strings, but just fix-length strings(in our example < 15). If you know the strings foo_A will manage never exceed a fixed small size, you may choose such style, otherwise you choose style like foo_B.
foo_C can be regarded as a mixture of both, variable-length but in-place allocation. It can be used as following:
/*
foo_C.c
str1, str2 remain the same
*/
#define BUF_SIZE 1024
int main() {
struct foo_C *foo_C = (struct foo_C *)malloc(BUF_SIZE);
memset(foo_C, 0, BUF_SIZE);
strcpy(foo_C->str1, str1);
strcpy(foo_C->str2, str2);
/*
safely manipulate foo_C strings
...
*/
free(foo_C);
}
You get foo_C from malloc rather than define it on stack or as static variable, so as to make foo_C of variable size. You access strings of foo_C directly without first allocating space for them. A key difference between foo_C and foo_A is that, str2 of the former can be of variable length, while that of the latter is fixed. As for variable-length, foo_C is also differnt from foo_B. For foo_C, the variable string space is always allocated with foo_C, while for foo_B, it can be allocated anywhere on heap and you must attach it manually.
Note if you just define foo_C on stack or as static variable, then str2 of it looks like non-existent. That is, sizeof(struct foo_C) equals STR_SIZE. You should never access str2, which may behaves like array out-of-bound.
As far as I know, only kernel code which manages slab allocator makes use of such hack.
This question already has an answer here:
Definitive List of Common Reasons for Segmentation Faults
(1 answer)
Closed 2 years ago.
I am just trying to understand why i get a segmentation fault when I use char *name as the member of the struct name... as apposed to char name[30] as the member, which works properly.
thankyou.
struct name
{
char *name1; // if i make this char name[30]; it works properly
};
void name_prompt(struct name *ptr)
{
printf("name: ");
scanf("%s", ptr->name1);
}
int main ()
{
struct name dylan;
struct name *ptr = &dylan;
name_prompt(ptr);
printf("%s", dylan.name1);
}
char name[30]; actually allocates 30 bytes of space within the struct for reading into. char* name just declares name as a pointer, saying that it could possibly be pointing to allocated space, but not necessarily. You never actually allocate space, so it segfaults.
On a side note, you should use %30s instead of %s for security reasons. (see here)
With a char*, you don't actually have any memory allocated to hold the data you're reading in. You didn't initialize the pointer, so it's pointing to some (semi-)random place, and writing to where it points is undefined behavior, so anything can happen.
If you want it to work with a char*, you'd need to malloc some storage for the pointer to point to (ideally freeing it when you're done), e.g.
int main ()
{
struct name dylan;
dylan.name = malloc(50); // Allocates space for up to 49 characters plus a NUL terminator; limit the scanf to match
name_prompt(&dylan);
printf("%s", dylan.name1);
free(dylan.name); // Release the memory
}
Using the array means the struct itself contains the memory wherever the struct was placed (so the struct is much larger, but doesn't rely on additional memory being allocated to be fully functional), in this case on the stack.
This is my struct:
typedef struct Person {
char* name;
int age;
float height;
float weight;
char** hobbies;
}person;
I tried to fill the name but it just ain't working.
void main(){
person Asaf;
char buffer[50];
int length;
puts("Please enter the name of the student");
gets(buffer);
length = strlen(buffer);
Asaf.name = realloc(buffer, length);
}
I just can't figure the problem...
I guess it has something to do with the realloc function.
please help!! :P
You are trying to realloc (which operates on the heap) an array that is allocated on the stack, which is a no-no. What you want instead is something like:
Asaf.name = strdup(buffer); /* POSIX: allocates a string copy of buffer on the heap */
Or, more standardly:
Asaf.name = (char*) malloc(strlen(buffer) + 1); /* TODO: should check allocations for NULL return */
strcpy(Asaf.name, buffer);
Also, you should use fgets() rather than gets(). gets() is inherently dangerous and should never be used because it doesn't do any bounds checking on the array to which it writes.
fgets(buffer, sizeof(buffer), stdin);
This function returns a pointer to the newly allocated memory, or NULL if the request fails.
so as realloc operates on heap here getting pointer to the memory allocation in heap area to a pointer guy sitting in stack can cause some problems buddy.
so maybe undefined behavior can be the answer for the output you are getting.
About how using realloc, all the didactic examples include this-
Use realloc:
1>Check if it's NULL.In this case use perror and exit the program
2>If it's not NULL use the memory allocated
3>Free the memory when you don't need it anymore.
possible duplicate of:How to use realloc in a function in C
I want to store a string in char array I am trying to do so by using a memcpy() but I am getting a segmentation fault. Can someone explain why? And what could be the correct way of doing this.
What would be better to use char * name; or char name[100]; ?
#include <stdio.h>
struct A
{
char * name;
};
typedef struct A A ;
int main()
{
A *a;
memcpy(a->name,"hello",sizeof(A));
printf("The value of name is %s",a->name);
return 0;
}
You have to allocate memory for structure and it's member and then after you can do copy data in it.
A *a = malloc(sizeof(A));
a->name=malloc(100); //change the size other then 100 what ever you want.
In first place you are asking two questions. You should read a bit here in order to understand how to ask good questions and get good answers.
You get segmentation fault because you haven't allocated memory for you variable name. The fastest way to solve this according the code and description you have provided is to use char name[100] in your declaration. Bear in mind that this is not the only possible way to do things. It depends what you are doing.
struct A
{
char name[100];
};
Then you have to allocate memory for the A *a pointer you are declaring. Better would be to use a normal variable A a and then access the member with the point operator (not sure if that is really an operator but the correct words doesn't come to mind at the moment). A simple snippet would be:
...
A a;
memcpy(a.name, "hello", 6);
printf("The value of name is %s",a.name);
...
A bit of documentation doesn't harm: memcpy()
I've written a function that uses fscanf("%s &d &d &d") to read from a file. For some reason, when I display the output, all the integer values are correct, but the strings are all the same. food_stuff is a struct held in an array.
*EDIT
I've tried using a for to add each element from one array to the other, and I've tried strcpy.
Here's the function.
int readFromFile()
{
char*name;
int type;
int cals;
int price;
FILE * food_file;
food_file = fopen ("food_file.txt", "r");
while(fscanf(food_file, "%s %d %d %d", name, &type, &cals, &price)!=EOF)
{
food_stuff fs;
fs.name = name;
fs.type = type;
fs.calories = cals;
fs.price = price;
fflush(stdin);
addItem(fs);
}
}
As a commenter already has pointed out, you need to allocate memory for your variable name. Because the variable is temporary, you could just declare a local char array on the stack instead of allocationg memory on the heap:
char name[40];
Your problem is that the name field in your structure is probably also only a pointer to char. That pointer points to name for all footstuff structs you generate, which is the same for all instances, only with different contents. (What's worse: That buffer won't exist any more if you leave readFromFile, invalidating the name field for every foodstuff.)
One possible solution is to make the name field also a buffer, e.g:
typedef struct food_stuff food_stuff;
struct food_stuff {
char name[40];
int type;
int cals;
int price;
};
When you assign the read data to the struct, don't copy the pointer, but copy the contents with strcpy. (You need to include <string.h> for that):
strcpy(fs.name, name);
This solution assumes that all names are less than 39 characters long, which is not a safe assumption for real data. You should specify a width on the %s format in your call to fscanf.
Another solution is leave the struct definition as I assume it is now with char *name and to allocate memory for each new struct. You still have to copy the contents, though:
fs.name = malloc(strlen(name) + 1);
// error check omitted
strcpy(fs.name, name);
This solution requires that you free the extra memory allocated when you free the foodstuff structs.