I'm trying to emulate a constructor. I'm attempting to do this by having a parent Struct have a function pointer that returns a pointer to a child struct. Any help would be much appreciated.
#include <stdio.h>
#include "stdlib.h"
typedef struct child_t {
char *name;
} Child;
typedef struct parent_t {
Child (*NewChild)();
} Parent;
Child *NewChild() {
Child *child = malloc(sizeof(Child));
child->name = "foo";
return child;
}
int
main()
{
Parent parent;
Child child = parent.NewChild();
}
A segmentation fault usually occurs when you try to access data via pointers for which no memory has been allocated. It is thus good practice to initialize pointers with the value NULL, and set it back to NULL after the memory has been released.
If the memory has been reallocated to another process, then attempting to dereference the dangling pointer can cause segmentation faults (UNIX, Linux) or general protection faults (Windows).
Rarely, a segmentation fault can be caused by a hardware error, but for our purposes we will be taking a look at software-based memory access errors. Although, segmentation faults are the result of invalid memory access, incorrect access to memory will not always result in a segmentation fault.
It seems like you haven't initialized parent.NewChild
. Try setting that to the function pointer before calling it, like this: parent.NewChild = NewChild;
.
Also, aren't you missing the *
in Child *child = parent.NewChild();
?
Addendum: By the comments, there is also an error/conflict in the declaration of Parent
:
Its NewChild
member function is declared to return a Child
, while the free method NewChild
returns a Child*
. So declare the member function pointer as Child * (*NewChild)();
.
I think you mean the following
#include <stdio.h>
#include <stdlib.h>
typedef struct child_t {
char *name;
} Child;
typedef struct parent_t {
Child * ( *NewChild )( void );
} Parent;
Child * NewChild( void )
{
Child *child = malloc( sizeof( Child ) );
child->name = "foo";
return child;
}
int main( void )
{
Parent parent = { NewChild };
Child *child = parent.NewChild();
puts( child->name );
free( child );
}
The program output is
foo
That is you should declare the function correctly. Its return type must be a pointer. So you must to declare the function pointer correctly in the structure definition
typedef struct parent_t {
Child (*NewChild)();
^^^^^^
} Parent;
And you need to initialize the object of type Parent.
Parent parent = { NewChild };
otherwise it has an indeterminate value.
I see the following problems in your code.
Mismatching function and function pointer
In Parent
, you have defined NewChild
as:
Child (*NewChild)();
That says NewChild
is a pointer to a function that takes no arguments and returns a Child
object.
The function that you have defined:
Child *NewChild() { ...
Takes no arguments and returns a pointer to a Child
, not an object of Child
.
You'll have to decide which one needs to be fixed. To fix the function, make its return type Child
.
Child NewChild() { ...
Uninitialized Child
of parent
You have left the value of parent.Child
uninitialized yet you are trying to use it.
Setting the member of Child
You use the following code to set the name
of child
.
child->name = "foo";
This may or may not be a problem depending on how you use child->name
since child->name
points to some global data in the computers read-only memory. It will be better to make a copy of "foo"
.
Here's my suggestion for updating your code:
Child NewChild()
{
Child child;
// strdup is available on some platforms but it can
// be implemented easily.
child->name = strdup("foo");
return child;
}
int main()
{
Parent parent;
parent.NewChild = NewChild;
Child child = parent.NewChild();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With