I am a bit confused at least.
getaddrinfo() call 'updates' a pointer to a addrinfo struct, all is well when I am going to use the addrinfo in the same scope (that function) but what happens if I copy the struct to another one (by assigning it).
Please help me understand the undergoing basics (not seeking advice for alternative approaches).
Correct me if I am wrong:
a) getaddrinfo() requires a pointer to struct-pointer to addrinfo.
b) getaddrinfo creates a addrinfo struct in the current function scope and updates the pointer required in a)
Now my real question: i would like to store that addrinfo somewhere else. Using an assigning to an other pointer does not do a deep copy, and after the function all the pointers become invalid?
Better give an extremely simplified example:
void GetAddrInfo(struct addrinfo *update)
{
struct addrinfo *res;
getaddrinfo(xx,xx,xx,&res);
//is this save? After this 'scope' ends all pointed fields are invalid?
//this doesn't copy the linked list ai_next.
*update=*res;
}
Directly using &update on getaddrinfo seems to not work because the problem remains: the original struct get destroyed after the function scope ends.
Anyone able to give me more insight here (please explain what gets created where and destroyed where, stack, heap all info is welcome)
the original struct get destroyed after the function scope ends
No, the struct's pointer is destroyed. The rest of the data is still in the heap. This would be a memory leak if you don't call freeaddrinfo() when you're finished with the result.
i would like to store that addrinfo somewhere else
Since the data still exists, feel free to copy the pointer; no need for a deep copy. From your example:
void GetAddrInfo(struct addrinfo **update) /* pointer to pointer */
{
struct addrinfo *res;
getaddrinfo(xx,xx,xx,&res);
*update=res; /* save the pointer to the struct */
}
You would simply call this function with:
struct addrinfo *mycopy;
GetAddrInfo(&mycopy);
getaddrinfo allocates a list of addrinfo structures, and gives you the pointer to the head of the list. You release all allocated memory by passing this pointer to freeaddrinfo when you're done with it.
What you're doing is safe enough, but leaks memory.
void GetAddrInfo(struct addrinfo **update)
{
getaddrinfo(xx,xx,xx,update);
}
addrinfo * myai;
GetAddrInfo(&myai);
freeaddrinfo(myai)
This approach will not leak memory - you're simply retrieving a pointer to the addrinfo list head.
Related
Assume I have a struct node like such:
struct node {
struct other_struct value;
int some_num;
}
I have seen snippets of code where the struct can be initialized without calling malloc, like this:
struct node my_node;
my_node.value = NULL;
my_node.some_num = 2;
And then value can later be malloced. However, how would I free my_node?
my_node is allocated on the stack, and once it goes out of scope, its memory is automatically deallocated.
Use malloc if you want to allocate something on the heap, and it will persist until you free it. For your example, you would do:
struct node *my_node = malloc(sizeof(struct node));
my_node->some_num = 2;
// Sometime later
free(my_node);
Space will also be allocated for the value field if you malloc (as long as you pass the right size) or if you declare on the stack. sizeof(struct node) includes the size of other_struct.
Currently with those code snippets you can't really free value or my_node, as they're both just static variables, if in your node structure, the other_struct field was a pointer, then you could dynamically allocate some memory, and save the address in that pointer.
Then when done, free the pointer value.
If then, my_node was also a pointer (which I think is what you want), you would need to allocate memory for the node struct, and save the address to the pointer my_node. THEN, allocate some memory for the other_struct struct and save it to the pointer value. And after you're done, you would free value FIRST, then free my_node.
When doing things like this, I generally create a little constructor/destructor function, which will do it all for me. It can be too easy to forget to free the inner pointer (value) and just free the outer pointer (mynode). Then that would cause a memory-leak, as value would still be allocated and taking up room in memory.
The code:
struct node {
struct other_struct value;
int some_num;
};
defines value to be a member of struct node. It is a part of struct node. Whenever a struct node is created, it will contain the member named value, and no other memory needs to be allocated for value. Whether a struct node is created automatically or by malloc or other means, its memory will always include memory for value.
If you changed it to:
struct node {
struct other_struct *value;
int some_num;
}
then value would be a pointer to a struct other_struct, and you would need to provide memory for it to point to.
In this code:
struct node my_node;
my_node.value = NULL;
my_node.some_num = 2;
the object my_node is created automatically, and you do not have to do anything to release it or its members; that will happen automatically. You cannot use my_node.value = NULL because value is a structure, not a pointer.
If the structure definition is changed so that value is a pointer, then you can set to NULL, or you can set it to point at an existing object, or you can allocate memory for it and set it to point to the allocated memory. If you allocate memory for it, then you should ensure that memory is later freed (except it is okay not to free it if you are intentionally keeping it to the end of program execution anyway, and you are executing in user mode on a general-purpose operating system).
You don't free it... it is destroyed, when the block it has been declared in is abandoned by the program.
Let's say that this variable is defined at the beginning of a function's body block. When the function is being called, the function creates this variable as it's a local. When the function terminates, all local variables are destroyed, so it is your local structure.
If you declare such a variable out of any function, then your variable has global duration, and it is created at program initialization, and lives as much as the program itself.
I'm new to C and socket programming, just a question on getaddrinfo function. The function prototype of getaddrinfo is:
int getaddrinfo(const char *host, const char *service, const struct addrinfo *hints, struct addrinfo **result);
and getaddrinfo returns a result that points to a linked list of addrinfo structures, each of which points to a socket address structure that corresponds to host and service.
Below is my questions:
Q1-Why it needs to return a result that points to a linked list of addrinfo structures? I mean that given a host and service, these is only one unique socket address, how could it be more than one valid socket address so that a linked list is needed?
Q2-the last parameter is struct addrinfo **result, why it is a pointer to a pointer? Why it is not struct addrinfo *result, and then getaddrinfo creates sth internally and let result(struct addrinfo *) point to it?
someone says it is due to getaddrinfo call malloc internally, but I can also code like this
int main()
{
char *ptr_main;
test(ptr_main);
free(ptr_main);
}
void test(char * ptr)
{
ptr = malloc(10);
}
so the parameter to the function is char *ptr, not char **ptr.
getaddrinfo() returns a list of address because an hostname can have more than an address. Think for example to those high traffic sites that need to distribute visitors through different IPs.
Since getaddrinfo()
combines the functionality provided by the gethostbyname(3) and getservbyname(3) functions into a single interface, but unlike the latter functions, getaddrinfo() is reentrant and allows programs to eliminate IPv4-versus-IPv6 dependencies
it might trigger a DNS session to resolve an host name. In case of those aforementioned high traffic sites the same hostname will correspond to a list of actual addresses.
You also ask:
struct addrinfo **result, why is it a pointer to a pointer?
In C a pointer to something is passing as a parameter of a function when it has to modify it. So, for example, in case you need to modify an integer, you pass int *. This particular kind of modification is very common in C when you want to return something through a parameter; in our previous example we can return an extra integer by accessing the pointer passed as a parameter.
But what if a function wants to allocate something? It will result, internally in a type * var = malloc(), meaning that a pointer to type would be returned. And in order to return it as a parameter we need to pass a type ** parameter.
Is it clear the logic? Given a type, if you wat to return it as a parameter you have to define it as a pointer to type.
In conclusion, in our case the function getaddrinfo needs to modify a variable which type is struct addrinfo *, so struct addrinfo ** is the parameter type.
Just to mention the meaning of this parameter:
The getaddrinfo() function allocates and initializes a linked list of addrinfo structures, one for each network address that matches node and service, subject to any restrictions imposed by hints, and returns a pointer to the start of the list in res. The items in the linked list are linked by the ai_next field.
As you can see we actually have an allocation inside the function. So this memory will need to be eventually freed:
The freeaddrinfo() function frees the memory that was allocated for the dynamically allocated linked list res.
Why not just a type * parameter?
Your code example results in undefined behavior, and when I run it it caused a program crash.
Why? Is I wrote above, in C parameters are passed by value. It means that in case of a func(int c) function, called in this way
int b = 1234;
funct(b);
the parameter c internally used by the function will be a copy of b, and any change on it won't survive outside the function.
The same happens in case of func(char * ptr) (please note the huge spacing, to underline how the type is char * and the variable is ptr): any change on ptr won't survive outside the function. **You'll be able to change the memory it points, and these changes will be available after the function returns, but the variable passed as a parameter will be the same it was before the call to func().
And what was the value of ptr_main, in your example, before test was called? We don't know, as the variable is uninitialized. So, the behavior is undefined.
If you still have doubts, here it is a program that demonstrates that the newly allocated address obtained by value cannot be accessed from outside the function:
#include <stdlib.h>
#include <stdio.h>
void test(char * ptr)
{
ptr = malloc(10);
printf("test:\t%p\n", ptr);
}
int main()
{
char *ptr_main = (char *) 0x7777;
printf("main-1:\t%p\n", ptr_main);
test(ptr_main);
printf("main-2:\t%p\n", ptr_main);
}
Output:
main-1: 0000000000007777
test: 0000000000A96D60
main-2: 0000000000007777
Even after the function call the value of ptr_main is the same it after I initialized it (0x7777).
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
I have a function that allows me to set some void *user_data which I am using to store a pointer to a struct job_data defined as:
struct job_data {
int *i
struct *j;
}
It does this by allowing me to pass my pointer to the user_data setting function through the call, so if I've got struct job_data job_info, I would set it via set_user_data(&job_info) where *set_user_data* receives a void * as a parameter.
However, when I get my pointer back later and cast it via struct job_data *job=user_data, the pointers inside (job.i and job.j) are set to different pointers than in the original job_data structure that I had cast to void *. Why is that? What should I do differently to recapture my original i and j pointers?
Most likely the scope that allocated struct job_data job_info on the stack no longer exists when you retrieve your pointer.
If the scope has ended by the time you retrieve your pointer then the contents will most likely have been overwritten by then.
You can fix this by either making sure the scope is valid as long as the pointer has to be accessed or to allocate the struct on the heap (malloc and family).
I have a pointer to a struct. I call a routine that determines whether I need this struct and allocates space for it using malloc, returning the pointer to that area or zero if unused.
struct node *node_p;
node_p = need_this();
This works and I can properly access all the elements of the struct. One of the elements of struct node is *next which points to the next node struct and a pointer to a string but it's returning a pointer to a string that doesn't even exist in this routine.
node_p=find_string(node_p->next,"string");
However, this does return a pointer in the struct to the correct string.
struct node *node_p, *node_copy;
node_copy=find_string(node_p->next,"string");
The only difference is using a second pointer instead of the original. Am I doing something wrong here or must it be deeper into the called function? The problem with blaming the called function is I use it in multiple places for months without issue, however the other calls only look for the string and never go to 'next'.
EDIT: Further debugging has shown the problem actually lies with the pointer being passed to find_string and not the returned pointer. That changes the question and the problem so I need to open another question.
In this snippet:
struct node *node_p, *node_copy;
node_copy=find_string(node_p->next,"string");
you dereference node_p when it is not yet initialized (doesn't point to a legally allocated memory block). That's undefined behavior. You should set node_p to a legally allocated memory block of appropriate size first.
You need to allocate memory explicitly for every struct, i.e. allocate a new struct and set next pointer to point to it.
Pointers in C prior to initialization point to random place and you never should dereference them. Safe policy would be to init them to be NULLs.