C++: When there's an object inside another object created using constructor, does that inner object live in the stack or the heap? - heap-memory

I'm wondering where a struct inside a struct created from the constructor (by the "new" keyword) lives: is it in the stack or the heap?
Let's say I have these definitions to create a singly linked list:
struct Employee{
int code;
string name;
double wage;
};
struct Node {
Employee employee;
Node* next;
};
Whenever I create a pointer to a Node and then I assign new Node() to it, I understand I'm creating a Node object in the heap, and its fields can be dereferenced using the -> operator. But when I try to access a field of the inner struct I need to use the dot (.) operator, such as:
Node* pointer = new Node();
pointer->employee.name="John Doe";
So this makes me wonder if the Employee object was created inside the stack or the heap.
Basically: when an object is created in the heap, do all inner objects in its member variables get created in the heap as well?
Thanks!

Still in the heap! The 'new' operation will malloc on the heap about sizeof(Node) bytes, and it equals sizeof(Employee)+sizeof(Node*), so name is on the heap.
And you should know '.' is just a way for C/C++ compiler to access some member, it does nothing about memory about heap or stack.

-> and . have nothing to do whether the element lives on heap or stack. A -> is used, when you have a pointer, a . when you have an object. You could create a struct on the stack and access its values using a pointer:
struct Foo
{
int i;
};
Foo f; // object on stack
f.i = 5; // access object
Foo* p_f = &f; // get pointer to address of object (which is still on the stack)
p_f->i = 3; // access object through pointer
To answer your question: the node that pointer points to lives in the heap and so does the string pointer->employee.name.
Please note, that new is not the constructor, but a function Node() would be the constructor.

Anything new lives on the heap and must be explicitly released by calling delete. Everything else is in the stack.

Related

When do we use structure variable and structure pointer?

I created a structure for a linked list node in C as follows.
struct node
{
int data;
struct node *next;
} *START = NULL;
Then when I need to access the properties of the structure, I create a pointer to structure as follows.
struct node *node1;
node1 -> data = 12;
node1 -> next = NULL;
I want to know if we can use
struct node node1
instead of the current declaration and what changes would that make in the program.
Also, I want to know why *START=NULL is outside the structure and what its data type is ?
You need to allocate the memory for the struct. Here you have a simple function which appends the node to the end of the list
struct node
{
int data;
struct node *next;
} *START = NULL;
struct node *append(int data)
{
struct node *node1 = malloc(sizeof(*node1));
struct node *list = START;
if(node1)
{
node1 -> data = data;
node1 -> next = NULL;
if(list)
{
while(list -> next)
{
list = list -> next;
}
list -> next = node1;
}
else
{
START = node1;
}
}
return node1;
}
START is the variable of type pointer to the struct node.
struct node *node1;
node1 -> data = 12;
node1 -> next = NULL;
First, the above code doesn't initialize node1 to a valid memory address. It merely creates a pointer called node1 which can take the address of a variable of struct node type which hasn't been properly initialized.
You need to change the code to the following.
struct node *node1 = (struct node*)malloc(sizeof(struct node));
node1 -> data = 12;
node1 -> next = NULL;
The above will allocate memory for struct node type and initialize node1 with the address of the allocated memory.
Now let's get to your questions.
I want to know if we can use
struct node node1
instead of the current declaration and what changes would that make in the program.
You can use the above declaration in your program, but it will create node1 on stack rather than on heap. Probably this is not the behaviour you want since the variable made on stack has the lifetime of the scope in which it's created. In your case I assume you want to create a linked list (or similar structure), therefore you need the list to be accessible even after the function in which the appending happens returns.
Anyway, if you created the variable on stack you can simply use . operator to access structure members.
struct node node1;
node1.data = 12;
node1.next = NULL;
Also, I want to know why *START=NULL is outside the structure and what
its data type is?
It simply defines a pointer variable named START that can point to struct node and initialize it with NULL.
[...] when I need to access the properties of the structure, I create
a pointer to structure as follows.
struct node *node1;
node1 -> data = 12;
node1 -> next = NULL;
Not exactly. You have declared node1 as a variable of type struct node *, but you have not created a pointer, in the sense that you have not given that variable a value that points to any structure. Subsequently attempting to access a struct node via that variable's (indeterminate) value therefore produces undefined behavior. Among the more likely outcomes are that your program crashes or that unexpected changes are made to random objects in its memory.
To be able to use node1 to access a struct node as you show, you first need to assign it to point to one (or at least to memory that can be made to contain one). You can do that either by assigning it the address of an existing struct node or by allocating memory sufficient for a struct node and assigning its address to node1. More on those alternatives later.
I want to know if we can use
struct node node1
instead of the current declaration and what changes would that make in
the program.
You definitely can declare node1 as a struct node instead of as a pointer to one. In the scope of such a declaration, you would access its members via the direct member-access operator (.) instead of via the indirect one (->):
node1.data = 12;
node1.next = NULL;
Furthermore, one of the ways to obtain a pointer to a struct node would be to use the address-of operator (&) to obtain that structure's address:
struct node *node_ptr = &node1;
HOWEVER, the lifetime of the node1 object declared that way ends when control passes out of the innermost block in which the declaration appears (if any), any pointers to it notwithstanding. As such, that usually is not what you want for a linked-list node.
For linked-list applications (among others), one generally wants an object whose lifetime doesn't end until you say it should do, and that can be achieved by dynamically allocating memory for the structure. For example,
struct node *node_ptr = malloc(sizeof(*node_ptr));
The allocated memory remains allocated until you explicitly free() it, whether in that scope or in another. Either way, to access the structure members through a valid pointer, one uses the indirect access operator, as in your example:
node_ptr->data = 42;
node_ptr->next = NULL;
or, equivalently, one first dereferences the pointer and then uses the direct member access operator:
(*node_ptr).data = 42;
(*node_ptr).next = NULL;
.
Also, I want to know why *START=NULL is outside the structure and what
its data type is ?
You said that you wrote the code. If you don't know the significance of the *START=NULL part, then what is it doing in your code?
In any event, it is analogous to the *node_ptr = &node1 above. START is declared (at file scope) as a pointer to a struct node, and its initial (pointer) value is assigned to be NULL, which explicitly and testably does not point to any structure.
When do we use structure variable and structure pointer?
Depends on the use case. When you create a structure variable you actually allocate the structure object on the stack. When you use pointer you usally allocate the structure object in heap memory and point to this object via the pointer.
You can resize and deallocate the dynamically allocated structure object whenever you want to, while the static can't be changes in size and it is only destroyed once the scope of it ends (in case of an automatic structure variable).
More details to the difference between static vs. dynamic allocation you can find in the links below the answer.
Which way you choose, depends on what you want to do and how you want to do it.
I want to know if we can use struct node node1 instead of the current declaration and what changes would that make in the program.
That would make node1 a variable of the structure itself; it would not be a pointer to an object of the structure only anymore.
Beside the things mentioned above and others, the access to the members would be different:
node1 . data = 12;
node1 . next = NULL;
Also I want to know why *START=NULL is outside the structure and what it's data type is.
START is of type struct node * (a pointer to struct node) and initialized to NULL. It's definition is outside because it isn't a member, it is a pointer to an object of the structure.
Note that you need to assign a pointer to struct node to point to an object of struct node, but that is not what you did at:
struct node *node1;
node1 -> data = 12;
node1 -> next = NULL;
So, this would invoke undefined behavior.
Allocate memory for the structure:
struct node *node1 = calloc (1, sizeof(*node1));
if (!node1)
{
fputs("Failure at memory allocation for node1!", stderr);
return EXIT_FAILURE;
}
node1 -> data = 12;
node1 -> next = NULL;
Related regarding point 1.:
What and where are the stack and heap?
Stack variables vs. Heap variables
Why would you ever want to allocate memory on the heap rather than the stack?
Which is faster: Stack allocation or Heap allocation

Using a function call to implement a stack

I'm a little unclear on this part of C, since it's a bit unlike other languages I've used, but this may just be a dumb question. I'm trying to implement a stack. I have the node struct, it has the information I want to pass:
struct position{
int square[2];
int counter;
struct position *prev;
};
so in main, I declare and initialize the bottom node of the stack, set *prev to NULL, then declare the rest. My question is, what happens when I try to pass it to function pop? I can create a position object that points to this one and return that, but will it be pushed off the stack when the function closes? Or should I return the position and set that equal to a new position object in main? What if I decide to create several of these nodes in a function? Will they remain once the function closes?
Edit: mah reminded me of my followup question which is, if they don't exist outside of the function, should I use malloc to create the space in the memory for them?
The lifetime of your objects depend on where they're created; if you declare for example a structure within a block of code (where a block is everything inside { and its matching }), that structure is no longer valid once execution leaves the block. Pointers to that structure are only valid as long as the structure is valid.
For what you're describing, you want to dynamically allocate your structures, using either malloc() or a similar function. Dynamically allocated data will remain valid (assuming you do not overwrite it) until you free() the memory, or until your program terminates. Pointers to these areas of memory will remain valid for that same period of time.
Consider:
static struct position *topOfStack = NULL;
void push(struct position *node)
{
node->prev = topOfStack;
topOfStack = node;
}
struct position *pop()
{
struct position *popped = topOfStack;
if (topOfStack) topOfStack = topOfStack->pref;
return popped;
}
To use this, you can:
f() {
struct position *node = malloc(sizeof(*node));
/* ... fill in node details ... */
push(node);
}
Notice that I allocated the node dynamically. Had I just declared a struct position node;, I could legally call push(&node); but once my function left scope, the stack would have an invalid item in it (which would likely cause havoc).
what happens when I try to pass it to function pop?
it depends on your pop() function prototype. If the pop's function prototype should be:
struct position* pop(struct position* stack);
I can create a position object that points to this one and return that, but will it be pushed off the stack when the function closes?
your question is quite unclear, and it looks like a big misunderstanding of instance scoping in C. Basically, you have two ways to allocate variables, either on the stack or on the heap. The scoping you're talking about is stack instances scope.
What if I decide to create several of these nodes in a function? Will they remain once the function closes?
basically, if you use the stack, they will live as long as the scope they're declared in. In C, scope is defined by { and }. for example:
int main() {
struct position pos1;
struct position pos2;
struct position pos3;
pos3.prev = pos2;
pos2.prev = pos1;
pos1.prev = NULL;
pop(&pos3);
}
there you declare 3 variables, and associate them, and the pop function just resets the .prev link. But for a stack that kind of architecture is not really useful, because it is quite limited.
There you definitely need to push your instances in the heap, thus using malloc() and free():
// push() pseudocode:
// take stack, iterate over each prev until prev is NULL
// allocate prev with malloc() the same way as for "stack" in main()
// insert values in prev
void push(struct position* stack, int* value);
// pop() pseudocode:
// take stack, iterate over each prev until prev->prev is NULL,
// then keep prev->prev in a temporary variable
// set prev to NULL
// return temporary variable (former prev->prev)
struct position* pop(struct position* stack);
int main() {
int value[2];
struct position* stack = malloc(sizeof(struct position));
// value is what you want to push to the stack
value[0] = 42;
value[1] = 42;
push(stack, value);
value[0] = 2;
value[1] = 20;
push(stack, value);
struct position* pos;
pos = pop(stack);
// do something with pos->value
free(pos);
}
there you create a pointer to a node for which you allocate some memory in the heap. the push() function is allocating some new memory, assigning .prev for that new space to stack's address and populating that memory with the value. pop() should get to the value before the last one, reset its pointer to that value, and return that value.
Of course, I'm just giving concepts and ideas here, I'm leaving you get to the real implementation. One advice though, instead of using square that contains an array, use two separate values in your struct, that will make it simpler for a first implementation.

allocating memory to a struct using malloc

I have a struct called State:
typedef struct State{
char alphabets[2][6];
struct State *PREV; /*this points to the previous state it came from*/
struct State *NEXT; /*this points to the next state in the linked list*/
int cost; /*Number of moves done to get to this position*/
int zero_index;/*this holds the index to the empty postion*/
} State;
Here's my memAllocator() method:
memAllocator(){
struct State *p = (State*) malloc(sizeof(State));
if (p==NULL){
printf("Malloc for a new position failed");
exit(1);
}
return p;
}
Here's my main method.
main(){
State *start_state_pointer=memAllocator();
State start_state;
start_state.zero_index=15;
start_state.PREV = NULL;
start_state.alphabets[0][0]='C';
start_state.alphabets[0][1]='A';
start_state.alphabets[0][2]='N';
start_state.alphabets[0][3]='A';
start_state.alphabets[0][4]='M';
start_state.alphabets[0][5]='A';
start_state.alphabets[1][0]='P';
start_state.alphabets[1][1]='A';
start_state.alphabets[1][2]='N';
start_state.alphabets[1][3]='A';
start_state.alphabets[1][4]='L';
start_state.alphabets[1][5]='_';
start_state_pointer=&(start_state);
/*start_state=*start_state_pointer;*/
}
I think the statement start_state_pointer=&(start_state); is just assigning the pointer start_state_pointer to to the small amount of temporary space created during State start_state, rather than to the space I allocated.
But when I try the commented out statement start_state=*start_state_pointer to deference the pointer and allocate the space to start state. It gives me a segmentation fault.
I am just starting out in C. Can some one help me with this?
Your memAllocator and main functions don't have explicit return types. This style of code has been deprecated for over 10 years. Functions in C should always have a return type. For main, the return type should be int, and for your memAllocator function, it should be State *.
The second issue is that you allocate space for a State struct, but then fill a different State struct and overwrite the pointer to the previously allocated State struct using start_state_pointer = &(start_state);.
To use the memory that you just allocated, you want to use something like this:
State *start_state = memAllocator();
start_state->zero_index = 15;
start_state->PREV = NULL;
start_state->alphabets[0][0] = 'C';
// etc.
There is no need to create two State structs. When you use State start_start; in your original code, you are creating a struct with something called automatic storage. This means the space for this struct is allocated automatically and is deallocated automatically for you at the end of the scope it is declared in. If you take the address of this struct and pass it around other parts of your program, then you will be passing around a pointer to a deallocated struct, and this could be why your program is crashing.

tsearch function does not maintain struct pointer within struct. Loss of information issue

I am using a tree in C to keep track of an undefined and varying number of input fields. I have a struct with a set number of fields as follows:
struct mystruct {
int id, mpid;
char *name;
struct myotherstruct *myostr;
};
I have a pointer instance of this type ( mystruct ) which I allocate memory for, then I fill these struct values in with input I've read from a file. I then use the tsearch function from search.h to add my mystruct object to the mystruct tree. The problem I am having, is that if I use the tfind function to retrieve a mystruct pointer from the tree, the mystruct memory that is returned has no recollection of the myotherstruct pointer data I allocated and pointed to when creating the value prior to adding to the tree.
The general sequence is as follows:
struct mystruct {
int id, mpid;
char *name;
struct myotherstruct *myostr;
};
struct myotherstruct {
int spid;
};
// allocate memory to temporary mystruct pointer
// add mpid field to mystruct pointer ( used in comparison function )
if( // tfind == NULL )
{
// set id value
// allocate char memory and strncpy correct value in
// allocate myotherstruct memory and assign all values
// tsearch for this newly created mystruct memory chunk so that it is added to tree
}
else
{
// fails here when attempting to access the data returned by mytfind
}
...
Using gdb, the program very clearly enters the if loop the first time ( since the tree is empty ) and creates a valid and full mystruct pointer with proper memory allocation. When tsearch returns it's output, the memory location is different from that of the mystruct pointer I filled in and then I am incapable of doing prints for mystruct->myotherstruct variables such as spid. The exact output I get when attempting to print in gdb is : Cannot access memory at address 0x----- where the -'s are various locations in memory that I apparently cannot access.
I suspect that there may be a problem with my comparison function since I am only comparing mystruct mpid fields to determine whether a tree node exists yet for a mystruct object, but my inexperience with both C and tsearch/tfind functionality are showing a bit here. Hopefully someone with more experience is able to help me since the examples provided on various tsearch.h webpages don't handle very sophisticated examples. Thanks in advance for the help!
PS: the code must remain in C, so language swapping doesn't suffice :(
EDIT:
here is my compare function:
int distcmp(const void *a, const void *b){
return ((int)((struct mystruct *)a)->mpid) != (int)(((struct mystruct *)b)->mpid);
}
Also, I use tfind initially because I want to know whether a particular value exists in the tree yet. If it does not exist ( it returns NULL ) then it enters the if loop and fills in the new mystruct object and adds it to the tree ( using tsearch ). If it already exists, a pointer to that object comes out of tfind which I assign to a mystruct pointer and use in the else portion of the code. Hopefully this helps. Thanks again.
SOLVED:
Just to update, the issue is that the returned pointer from tsearch and tfind is not of the type mystruct. It is a pointer to the memory location of the mystruct value that matched my search. In this case, the issue would be resolved by accessing the returned pointer with a * and passing that value to a mystruct pointer. Thanks to those who commented.

C generic linked-list

I have a generic linked-list that holds data of type void* I am trying to populate my list with type struct employee, eventually I would like to destruct the object struct employee as well.
Consider this generic linked-list header file (i have tested it with type char*):
struct accListNode //the nodes of a linked-list for any data type
{
void *data; //generic pointer to any data type
struct accListNode *next; //the next node in the list
};
struct accList //a linked-list consisting of accListNodes
{
struct accListNode *head;
struct accListNode *tail;
int size;
};
void accList_allocate(struct accList *theList); //allocate the accList and set to NULL
void appendToEnd(void *data, struct accList *theList); //append data to the end of the accList
void removeData(void *data, struct accList *theList); //removes data from accList
--------------------------------------------------------------------------------------
Consider the employee structure
struct employee
{
char name[20];
float wageRate;
}
Now consider this sample testcase that will be called from main():
void test2()
{
struct accList secondList;
struct employee *emp = Malloc(sizeof(struct employee));
emp->name = "Dan";
emp->wageRate =.5;
struct employee *emp2 = Malloc(sizeof(struct employee));
emp2->name = "Stan";
emp2->wageRate = .3;
accList_allocate(&secondList);
appendToEnd(emp, &secondList);
appendToEnd(emp2, &secondList);
printf("Employee: %s\n", ((struct employee*)secondList.head->data)->name); //cast to type struct employee
printf("Employee2: %s\n", ((struct employee*)secondList.tail->data)->name);
}
Why does the answer that I posted below solve my problem? I believe it has something to do with pointers and memory allocation. The function Malloc() that i use is a custom malloc that checks for NULL being returned.
Here is a link to my entire generic linked list implementation: https://codereview.stackexchange.com/questions/13007/c-linked-list-implementation
The problem is this accList_allocate() and your use of it.
struct accList secondList;
accList_allocate(&secondList);
In the original test2() secondList is memory on the stack. &secondList is a pointer to that memory. When you call accList_allocate() a copy of the pointer is passed in pointing at the stack memory. Malloc() then returns a chunk of memory and assigns it to the copy of the pointer, not the original secondList.
Coming back out, secondList is still pointing at uninitialised memory on the stack so the call to appendToEnd() fails.
The same happens with the answer except secondList just happens to be free of junk. Possibly by chance, possibly by design of the compiler. Either way it is not something you should rely on.
Either:
struct accList *secondList = NULL;
accList_allocate(&secondList);
And change accList_allocate()
accList_allocate(struct accList **theList) {
*theList = Malloc(sizeof(struct accList));
(*theList)->head = NULL;
(*theList)->tail = NULL;
(*theList)->size = 0;
}
OR
struct accList secondList;
accList_initialise(secondList);
With accList_allocate() changed to accList_initialise() because it does not allocate
accList_initialise(struct accList *theList) {
theList->head = NULL;
theList->tail = NULL;
theList->size = 0;
}
I think that your problem is this:
You've allocated secondList on the stack in your original test2 function.
The stack memory is probably dirty, so secondList requires initialization
Your accList_allocate function takes a pointer to the list, but then overwrites it with the Malloc call. This means that the pointer you passed in is never initialized.
When test2 tries to run, it hits a bad pointer (because the memory isn't initialized).
The reason that it works when you allocate it in main is that your C compiler probably zeros the stack when the program starts. When main allocates a variable on the stack, that allocation is persistent (until the program ends), so secondList is actually, and accidentally, properly initialized when you allocate it in main.
Your current accList_allocate doesn't actually initialize the pointer that's been passed in, and the rest of your code will never see the pointer that it allocates with Malloc. To solve your problem, I would create a new function: accList_initialize whose only job is to initialize the list:
void accList_initialize(struct accList* theList)
{
// NO malloc
theList->head = NULL;
theList->tail = NULL;
theList->size = 0;
}
Use this, instead of accList_allocate in your original test2 function. If you really want to allocate the list on the heap, then you should do so (and not mix it with a struct allocated on the stack). Have accList_allocate return a pointer to the allocated structure:
struct accList* accList_allocate(void)
{
struct accList* theList = Malloc( sizeof(struct accList) );
accList_initialize(theList);
return theList;
}
Two things I see wrong here based on the original code, in the above question,
What you've seen is undefined behaviour and arose from that is the bus error message as you were assigning a string literal to the variable, when in fact you should have been using the strcpy function, you've edited your original code accordinly so.. something to keep in mind in the future :)
The usage of the word Malloc is going to cause confusion, especially in peer-review, the reviewers are going to have a brain fart and say "whoa, what's this, should that not be malloc?" and very likely raise it up. (Basically, do not call custom functions that have similar sounding names as the C standard library functions)
You're not checking for the NULL, what if your souped up version of Malloc failed then emp is going to be NULL! Always check it no matter how trivial or your thinking is "Ah sher the platform has heaps of memory on it, 4GB RAM no problem, will not bother to check for NULL"
Have a look at this question posted elsewhere to explain what is a bus error.
Edit: Using linked list structures, in how the parameters in the function is called is crucial to the understanding of it. Notice the usage of &, meaning take the address of the variable that points to the linked list structure, and passing it by reference, not passing by value which is a copy of the variable. This same rule applies to usage of pointers also in general :)
You've got the parameters slightly out of place in the first code in your question, if you were using double-pointers in the parameter list then yes, using &secondList would have worked.
It may depend on how your Employee structure is designed, but you should note that
strcpy(emp->name, "Dan");
and
emp->name = "Dan";
function differently. In particular, the latter is a likely source of bus errors because you generally cannot write to string literals in this way. Especially if your code has something like
name = "NONE"
or the like.
EDIT: Okay, so with the design of the employee struct, the problem is this:
You can't assign to arrays. The C Standard includes a list of modifiable lvalues and arrays are not one of them.
char name[20];
name = "JAMES" //illegal
strcpy is fine - it just goes to the memory address dereferenced by name[0] and copies "JAMES\0" into the memory there, one byte at a time.

Resources