I have a while loop, where in each itteration of the while loop I malloc a struct object. Then at the end of the loop I add it to the end of a linked list. Now my concern is, I have the same variable name when I malloc each time in the loop, so I dont understand how this works after I attach the lastest malloced object to the linked list, what happens to the others that I malloced that had the same name.
My code:
struct Student{
char *name;
int IDno;
}Student;
someFunction(){
x = 0;
while(x!=6){
Student *name = malloc(sizeof(Student)); <----- Confusion here
addToLinkedList(LinkedListStruct,name);
}
Is it alright that I have name being malloced each time in the loop. Can someone explain to me what happens if I malloc in this way, add it to the end of a linked list and then go into the next loop and do this same.
The malloc() call has no relationship to the name of the variable you assign its return value to. malloc() doesn't know that you assign its return value to a variable named name. What you do is completely valid and well-defined.
There is still an error with your code though as malloc() returns a pointer to a memory area, not the memory itself. Thus the declaration should have been
Student *name = malloc(sizeof (Student));
Related
I am new to C and I try to create a function return a pointer. I used different ways to do it:
1.
typedef struct student{
int age;
}student;
student *create_student(){
student* s;
s-> age= 24;
return s;
}
int main() {
student* s = create_student();
printf("the student age is %d", s->age);
return 0;
}
It compiles but doesn't seem to work.
2.
typedef struct student{
int age;
}student;
student *create_student(){
student* s;
student s2;
s2.age = 24;
s = &s2;
return s;
}
int main() {
student* s = create_student();
printf("the student age is %d", s->age);
return 0;
}
It seems to work, and print "the student age is 24", but if I added one printf statement before previous printf:
int main() {
student* s = create_student();
printf("This is a test\n");
printf("the student age is %d", s->age);
return 0;
}
It gives me:
This is a test
the student age is -1422892954
3.
If I use following ways:
typedef struct student{
int age;
}student;
student *create_student(){
student* s = malloc(sizeof(student));
s -> age = 24;
return s;
}
int main() {
student* s = create_student();
// printf("This is a test\n");
printf("the student age is %d", s->age);
return 0;
}
It works in both cases, with and without the commented printf
I just want to know what are the reasons it fails for 1 and 2. And why it works for 3?
And generally speaking when should we use malloc and when we shouldn't?
Thanks
Example 1
Your example 1 doesn't work because no student object is ever created.
student* s;
This creates a pointer s that is supposed to point to a student but currently points to an unknown memory location because it is an uninitialized variable. It definitely doesn't point to a new student, since none was created so far.
s->age = 24;
This then writes to the unknown memory location that s is currently pointing to, corrupting memory in the process. You now entered the realm of undefined behavior (UB). Your process may crash at this very moment, or later on, or it may do something crazy and unexpected.
It doesn't make sense to think about what happens after this point, because your process is already doomed by now and needs to be terminated.
Example 2
Your example 2 sort-of works but only sometimes, because yet again UB comes into play.
student s2;
Here you are creating a student as a local variable. It is probably created on the stack. The variable is valid until you leave the function create_student.
However, you are then creating a pointer to that student object and returning it from your function. That means, the outer code now has a pointer to a place where a student object once was, but since you returned from the function and it was a local variable, it no longer exists! Sort of, that is. It's a zombie. Or, better explained, it's like when you delete a file on your harddisk - as long as no other file overwrote its location on the disk, you may still restore it. And therefore, out of sheer luck, you are able to read the age of it even after create_student had returned. But as soon as you change the scenario a bit (by inserting another printf), you ran out of luck, and the printf call uses its own local variables which overwrite your student object on the stack. Oops. That is because using a pointer to an object that no longer exists is also undefined behavior (UB).
Example 3
This example works. And it is stable, it doesn't have undefined behavior (almost - see below). That is because you create the student on the heap instead of the stack, with malloc. That means it now exists for eternity (or until you call free on it), and won't get discarded when your function returns. Therefore it is valid to pass a pointer to it around and access it from another place.
Just one small issue with that - what if malloc failed, for example you ran out of memory? In that case we have a problem yet again. So you should add a check for whether malloc returned NULL and handle the error somehow. Otherwise, s->age = 24 will attempt to dereference a null pointer which again won't work.
However, you should also remember to free it when you are done using it, otherwise you have a memory leak. And after you did that, remember that now your pointer did become invalid and you can no longer use it, otherwise we are back in UB world.
As for your question when to use malloc: Basically whenever you need to create something that lives on after you leave your current scope, or when something is local but has to be quite big (because stack space is limited), or when something has to be of variable size (because you can pass the desired size as argument to malloc).
One last thing to note though: Your example 3 worked because your student only had one field age and you initialized that field to 24 before you read it again. This means all the fields (since it had only that one) got initialized. If it had had another field (say, name) and you hadn't initialized that one, you would still have carried an "UB time bomb" if your code elsewhere would have attempted to read that uninitialized name. So, always make sure all fields get initialized. You can also use calloc instead of malloc to get the memory filled with zeroes before it's passed to you, then you can be sure that you have a predictable state and it is no longer undefined.
Because in case1 and 2, the variable "age" is in the sub-function create_student()'s scope, on a stack. So once the sub-function is finished, that area is released, which means that the "age" is released also. So s now points to a non-sense area. If you are lucky enough, that area still stores the "age", you can print that info out, that's why it works in case2's first part.
But in case3, student* s points to a heap area and when that sub-function is finished that heap area won't be free. So s->age still works.
Continuing from the comments, you can think of it this way:
Case 1.
student* s;
s in an uninitialized pointer that does not point to any memory you can validly use. It's value is indeterminate.
Case 2.
student* s;
student s2;
s2.age = 24;
s = &s2;
s is an uninitialized pointer (as in 1.), s2 declares a valid struct and s2.age is validly initialized. s = &s2; assigns the address of s2 (declared local to the function) to s. When s is returned, s2 is invalidated -- its life limited to the function, so the address return to main() is invalid.
Case 3.
student* s = malloc(sizeof(student));
Yes!! s now holds the starting address to a valid block of memory with allocated storage duration (good for the life of the program or until freed). The only problem is you need to validate the allocation succeeds:
if (s == NULL) {
perror ("malloc-s");
return NULL;
}
Now you can have confidence that the return is either a valid address or NULL indicating allocation failed.
When to use
To your last question, you dynamically allocate when you don't know how many of something you will need, so you declare some number of them, keep track of how many you have used, and realloc more when the initially allocated block is filled. Or, you need more of something than will fit on the program stack, you can allocate or declare as static (or declare globally). Otherwise, if you know how many you need beforehand, and that will fit on the stack, just declare an array of them and you are done.
Let me know if you have further questions.
I am new to C, and I am facing this problem when practicing.
The struct:
typedef struct {
char name[20];
int score[3];
int no;
} Student;
The initialize:
Student *pStudent;
strcpy(pStudent->name,"Kven");
pStudent->score[0]=1;
pStudent->score[1]=2;
pStudent->score[2]=3;
pStudent->no=1;
If the "pStudent" is not a pointer I can get it right. But if it is a pointer, I will always get a "bad access" error. How to solve it if I must use a pointer? Thank you.
A variable of type pointer stores the address in memory of another variable (it points to another variable).
Your variable pStudent is not initialized. It doesn't point to anything. In fact, it contains some garbage value that, most of the times, is the address of a memory area where the program is not allowed to write. This is why when you attempt to write there (the call to strcpy()) the operating system slaps your program over its "hand" and terminates it with the error message you mentioned.
How to correctly use pointers
One usage of pointers is to point to a certain variable that is statically allocated (defined in the program):
Student s, *pStudent = &s;
This example declares the variable s of type Student and the variable pStudent that points to it. Notice it is initialized with &s which is the address of s. Now, your code uses pStudent to initialize the fields of s.
Another usage of pointers is to dynamically allocate memory during runtime:
Student *pStudent;
pStudent = malloc(sizeof(Student));
In this situation, pStudent is initialized with the address of a new variable of type Student that is created during runtime (it doesn't have a name) by calling malloc(). malloc() allocates a block of memory (of the specified size) and return its address.
When you don't need it, you have to free the memory allocated by malloc() (using free()) for reuse:
free(pStudent);
After this call, the value of the variable pStudent doesn't change, it still points to the same address but it is invalid and using it produces undefined behaviour. You have to put the address of another Student structure in pStudent (using one of the two ways presented here) before using it again.
Student *pStudent;
should be
Student *pStudent = malloc(sizeof(Student));
Allocate memory for the pointer before writing data once done using it
free(pStudent);
Student *pStudent;
creates a pointer of type Student*. This pointer is not initialized and points to some "random" location. Allocate memory for it using malloc(or calloc) from stdlib.h:
pStudent = malloc(sizeof(Student));
and then free it after its use using:
free(pStudent);
You don't allocate any memory, you just allocate a pointer. You'll need to study pointers and how they work.
Fix the code like this:
Student student;
strcpy(student.name,"Kven");
student.score[0]=1;
student.score[1]=2;
student.score[2]=3;
student.no=1;
Alternatively you could allocate memory dynamically. But it doesn't make any sense in this case (and yet I bet at least 3 people will post answers telling you to do that...). Plus you really need to study pointers before doing dynamic allocation.
Student *pStudent = calloc(1, sizeof(Student);
if(pStudent == NULL)
{
// error handling
}
strcpy(pStudent->name,"Kven");
pStudent->score[0]=1;
pStudent->score[1]=2;
pStudent->score[2]=3;
pStudent->no=1;
...
free(pStudent);
You need to allocate memory for your structure first.
You can allocate memory with:
Student *pStudent = malloc(sizeof(Student));
And then you must release it at the end with
free(pStudent);
I made a linked list whose nodes hold 4 string values. When I call the newNode function, an error says 'Node has no member named familyName', as well as the other members. My code:
I am really confused with how strings work in structs.
Your immediate problem is the type definition. You cannot call malloc() from within there, all you can do is define the fields. The memory allocation must come later. So, it should be:
typedef struct node{
char *familyName;
char *firstName;
char *address;
char *phoneNumber;
struct node *link;
}Node;
You'll strike another problem (run-time rather than compile-time) once you fix that. When you do something like:
p -> familyName = famName;
that simply copies the pointer into your structure, and the pointer is always the memory location of familyName in main().
That means every node will point to the same memory, and you're continuously updating that memory.
You won't notice the problem with the code as it stands, since you're only asking for one record. But it will become an issue when you start looping to get more records.
Your best bet is to use something like strdup() to make a copy of the string passed in, then each node will have its own memory location for strings:
p -> familyName = strdup (famName);
(don't forget to also free() the memory for each field once you're finished with it).
In the unlikely event your C implementation doesn't have a strdup(), see here.
There are several problems:-
It is not allowed to allocate memory when declaring a structure. Either, do the malloc inside your newNode() method Or, declare the structure like char familyName[50].
Result of malloc should not be casted.
It is better to use strcpy (or strdup) when copying strings
This seems to be a very simple problem but I can't quite figure out which part is causing it. Basically, I have a struct that just contains an array of strings
struct command_stream{
char **tokens;
};
typedef struct command_stream *command_stream_t;
command_stream_t test;
Then later on, I parse some strings into shorter ones and end up with another array of strings
char **words = *array of strings*
words contains the correct information I want, I looped through and printed out each element to make sure I wasn't getting a faulty string. So now I just point tokens to words
test->tokens = words;
But it gives me a segmentation fault. I'm not sure why though. They're both pointers, so unless I'm missing something obvious...
EDIT: The function as a whole has to return a pointer, which is why it was set up like this, which I keep forgetting. But I think I've got it, if I just create a new typedef
typedef struct command_stream command_stream_s;
command_stream_s new_command_stream;
and just return
&new_command_stream;
That should work right? Even though new_command_stream itself isn't a pointer.
From your code excerpt, it seems that you have not declared the struct. You have successfully declared a pointer to the struct command_stream_t test; but this pointer does not point to anywhere yet.
You need to allocate memory for your struct in some way and make test reference it. For instance:
command_stream_t test =
(command_stream_t) malloc(sizeof(struct command_stream));
This way you can successfully use:
test->tokens = words;
as you intended.
Note that you don't need to use malloc to allocate the memory. The pointer can reference a local/global variable as long as it has memory associated to it (N.B. if you use a local var don't use the pointer outside the declaration scope of that var).
typedef struct command_stream *command_stream_t;
command_stream_t test;
This makes "test" a pointer. There is no memory allocated for the structure.
You need to allocate memory for the structure and make the test pointer point to the block of memory before you can dereference by saying -
test->tokens = words;
Do this:
typedef struct command_stream command_stream_t;
command_stream_t test;
test.tokens = words;
The difference is that, command_stream_t is no more a pointer type, it is the actual structure.
I am a java programmer learning C. Have a question regaring functions. What are the differences between this:
main()
{
struct person myperson;
myperson = myfunction();
return;
}
struct person myfunction()
{
struct person myPerson;
myPerson.firstname = "John";
myPerson.lastname = "Doe";
return myPerson;
}
VS
main()
{
struct person *myperson;
myperson = myfunction();
return;
}
struct person* myfunction()
{
struct person *myPerson;
myPerson = malloc(sizeof(struct person));
myPerson->firstname = "John";
myPerson->lastname = "Doe";
return myPerson;
}
Are these legal in C? And y would 1 choose one over the other.
Thanks so much guys!
first code sample:
you create a struct in myfunction() on your stack and return it. then, you create another stack struct, and you copy the first to the second. the first is destroyed. the second will be automatically destroyed when you are out of the scope.
2 structs were actually created.
second code sample:
you create a struct in myfunction(), and then you copy only the address. the struct in main will actually be the same struct.
only one struct is created in here.
both code samples work, but for the later you will have to explicitly free the memory allocated for the struct, to avoid memory leak, but performance should be better since you don't need to copy the struct!
EDIT:
as mentioned by #Mat: this of course neglects the overhead of malloc(), which is not true for small structs.
The first version allocates the object on the stack and returns a copy of it. The second version creates the object on the heap and returns a pointer to it(this is closest to Java references except that the memory isn't automatically freed). You should not forget to call free() later on the returned pointer.
Btw, your main function is bad. It should be
int main(void)
{
...
return 0;
}
I suggest that you should read a good C book. This is really basic stuff you're asking.
I'm not sure if all this talk of "heap" and "stack" is cutting to the core of the language, so let me try something more language-intrinsic.
Your first version uses only automatic allocation, which means that all variables have automatic lifetime. That is, all variables end their life at the end of their enclosing scope: myFunction creates a local variable of type struct person and returns a copy of that variable; the main function declares a local variable of the same type and assigns to it the result of the function call. At the end of each scope, the local variables end as well.
The second version uses dynamic or manual allocation. You explicitly allocate storage for a person variable with the malloc() call, and that storage will remain allocated until someone deallocates is (via free()). Since you never deallocate it, this is in effect a memory leak.
The fundamental difference is one of lifetime and responsibility.
A few pros and cons: Automatic allocation means that responsibility is local, and you generally don't have to worry about anything. However, it comes at the price of having to copy arguments and return values by value, which may be expensive or undesirable. Manual allocation allows you to refer to large amounts of memory via a simple, cheap pointer, and is often the only way to implement certain constructions, but carries the burden of having the author remember who's responsible for which resource.
Both are legal, both work.
The 1st version is simpler, you avoid having to deal with memory allocation and releasing.
The 2nd version will perform better for bigger structs because you avoid putting the whole struct on stack for handing it over.
I would actually choose a third way. Let the caller worry about providing storage space (auto or dynamically allocated):
void myfunction(struct person* myPerson)
{
myPerson->firstname = "John";
myPerson->lastname = "Doe";
}
The function can be called either with an automatically or dynamically allocated variable:
struct person autoperson;
myfunction(&person);
struct person dynamic_person = malloc(sizeof struct person);
myfunction dynamic_person);
The first will allocate a struct person on the stack, and pass a copy of it back, then free the original. The second one will allocate it on the heap and pass a pointer to the location which was allocated, and will not free it.
The first one allocates the variables on the stack. The person object from myfunction is copied from the function and returned which is less efficient, but you can't get a memory leak which is good.
The second example returns a pointer (the *) to a person object that is dynamically allocated (with malloc). The person object allocated by malloc will never be destroyed unless you explicitly call free() on it, hwich you haven't - so you have a memory leak.
You need to explicitly free memory in C, it doesn't have garbage-collection like Java.
The first option creates a struct on the stack, when returning it, it gets copied to your struct defined in the main() function. Also copied are the fields. For larger structs this can be a costly operation.
The second option allocates dynamic memory, which does not get copied when you return it. You have to free() the pointer to avoid a memory leak.
Of course it depends on your needs, but for more important and long living objects I'd go for the second option. Also I would recommend to write allocation/initialization functions and a corresponding deallocation function. (see below why)
The problem is that the 2 strings you set in myfunction() are invalid outside of the function, as they are also created on the stack. You have to use strdup() or a similar function to make this failsave. Of course, to not let memory leaks slip in you have to free() the strduped pointers, just as with malloc().
In the first code, myPerson is an object of type struct person that is managed (*) by the implementation itself. In the second code, it is an object of type struct person * (a pointer to a struct person). In the second code, the object itself must be managed by the programmer (malloc, realloc, free).
Also, in the first code, the object itself is copied around a few times whereas in the 2nd code "only" the pointer gets copied. Usualy a pointer is much smaller than an object of a struct type.
Use the 2nd approach but remember to free the object.
Even better, create the object in the parent function and pass a pointer to functions: sruct person *myfunction(struct person *data) { /* ... */ }
(*) with object management I mean the time it gets created and deleted and stuff
First One:
main()
{
// create a person struct on the stack
struct person myperson;
// copy the struct returned by myfunction to myperson.
myperson = myfunction();
}
struct person myfunction()
{
// create a person struct on the stack.
struct person myPerson;
myPerson.firstname = "John";
myPerson.lastname = "Doe";
// return the myPerson struct. After myFunction returns, the memory
// holding the myPerson struct on the stack will be freed.
return myPerson;
}
Second one:
main()
{
// create a pointer to a person struct on the stack
struct person *myperson;
// assign the pointer returned by myfunction to myperson
myperson = myfunction();
}
struct person* myfunction()
{
// create a pointer to a person struct on the stack
struct person *myPerson;
// allocate memory for a person struct in dynamic memory and set myPerson
// to point to that memory. This memory will remain valid until it's freed by
// a call to the "free" function. Using malloc is much slower than creating
// an object on the stack. There is also the added performance cost of
// freeing the allocated memory at a later stage.
myPerson = malloc(sizeof(struct person));
myPerson->firstname = "John";
myPerson->lastname = "Doe";
// return the myPerson pointer
return myPerson;
}