I'm trying to make a list of pointers to a structure called "thread". Here is my attempt:
//kmalloc is my malloc, don't worry
struct thread **process0 = kmalloc(sizeof(struct *thread));
//^ This line is giving me a parse error
And basically I want process0[0] to be a pointer to a thread,
process0[1] to be a pointer to another thread,
process0[2] to be a pointer to yet another thread,
etc.
Later I may want to access one of the thread's "addrspace" member (a pointer to an addrspace structure) along the following:
struct addrspace *test = process0[i][j]->addrspace;
Where I'm thinking proccess0[i] is a particular list of thread pointers, and process0[i][j] is a particular thread pointer from the particular list of thread pointers... Then I'd want to access one of its members via the -> operator.
I've always sucked at pointer arithmetic stuff and would like to get things cleared up. Thank you very much.
The datatype that you want is "pointer to struct thread", or:
struct thread **process0 = kmalloc(sizeof(struct thread *));
struct thread **process0 = kmalloc(sizeof(struct * thread)*NUM_THREADS*NUM_PROCESSES_IN_EACH_THREAD); //kmalloc is my malloc, don't worry
Before you were only allocating like one pointer, if I read it right. Does this help at all?
Related
Could someone please explain to me the difference between creating a structure with and without malloc. When should malloc be used and when should the regular initialization be used?
For example:
struct person {
char* name;
};
struct person p = {.name="apple"};
struct person* p_tr = malloc(sizeof(struct person));
p_tr->name = "apple";
What is really the difference between the two? When would one approach be used over others?
Having a data structure like;
struct myStruct {
int a;
char *b;
};
struct myStruct p; // alternative 1
struct myStruct *q = malloc(sizeof(struct myStruct)); // alternative 2
Alternative 1: Allocates a myStruct width of memory space on stack and hands back to you the memory address of the struct (i.e., &p gives you the first byte address of the struct). If it is declared in a function, its life ends when the function exits (i.e. if function gets out of the scope, you can't reach it).
Alternative 2: Allocates a myStruct width of memory space on heap and a pointer width of memory space of type (struct myStruct*) on stack. The pointer value on the stack gets assigned the value of the memory address of the struct (which is on the heap) and this pointer address (not the actual structs address) is handed back to you. It's life time never ends until you use free(q).
In the latter case, say, myStruct sits on memory address 0xabcd0000 and q sits on memory address 0xdddd0000; then, the pointer value on memory address 0xdddd0000 is assigned as 0xabcd0000 and this is returned back to you.
printf("%p\n", &p); // will print "0xabcd0000" (the address of struct)
printf("%p\n", q); // will print "0xabcd0000" (the address of struct)
printf("%p\n", &q); // will print "0xdddd0000" (the address of pointer)
Addressing the second part of your; when to use which:
If this struct is in a function and you need to use it after the function exits, you need to malloc it. You can use the value of the struct by returning the pointer, like: return q;.
If this struct is temporary and you do not need its value after, you do not need to malloc memory.
Usage with an example:
struct myStruct {
int a;
char *b;
};
struct myStruct *foo() {
struct myStruct p;
p.a = 5;
return &p; // after this point, it's out of scope; possible warning
}
struct myStruct *bar() {
struct myStruct *q = malloc(sizeof(struct myStruct));
q->a = 5;
return q;
}
int main() {
struct myStruct *pMain = foo();
// memory is allocated in foo. p.a was assigned as '5'.
// a memory address is returned.
// but be careful!!!
// memory is susceptible to be overwritten.
// it is out of your control.
struct myStruct *qMain = bar();
// memory is allocated in bar. q->a was assigned as '5'.
// a memory address is returned.
// memory is *not* susceptible to be overwritten
// until you use 'free(qMain);'
}
If we assume both examples occur inside a function, then in:
struct person p = {.name="apple"};
the C implementation automatically allocates memory for p and releases it when execution of the function ends (or, if the statement is inside a block nested in the function, when execution of that block ends). This is useful when:
You are working with objects of modest size. (For big objects, using many kibibytes of memory, malloc may be better. The thresholds vary depending on circumstances.)
You are working with a small number of objects at one time.
In:
struct person* p_tr = malloc(sizeof(struct person));
p_tr->name = "apple";
the program explicitly requests memory for an object, and the program generally should release that memory with free when it is done with the object. This is useful when:
The object must be returned to the caller of the function. An automatic object, as used above, will cease to exist (in the C model of computation; the actual memory in your computer does not stop existing—rather it is merely no longer reserved for use for the object) when execution of the function ends, but this allocated object will continue to exist until the program frees it (or ends execution).
The object is very large. (Generally, C implementations provide more memory for allocation by malloc than they do for automatic objects.)
The program will create a variable number of such objects, depending on circumstances, such as creating linked lists, trees, or other structures from input whose size is not known before it is read.
Note that struct person p = {.name="apple"}; initializes the name member with "apple" and initializes all other members to zero. However, the code that uses malloc and assigns to p_tr->name does not initialize the other members.
If struct person p = {.name="apple"}; appears outside of a function, then it creates an object with static storage duration. It will exist for the duration of program execution.
Instead of struct person* p_tr = malloc(sizeof(struct person));, it is preferable to use struct person *p_tr = malloc(sizeof *p_tr);. With the former, a change to the p_tr requires edits in two places, which allows a human opportunity to make mistakes. With the latter, changing the type of p_tr in just one place will still result in the correct size being requested.
struct person p = {.name="apple"};
^This is Automatic allocation for a variable/instance of type person.
struct person* p_tr = malloc(sizeof(person));
^This is dynamic allocation for a variable/instance of type person.
Static memory allocation occurs at Compile Time.
Dynamic memory allocation means it allocates memory at runtime when the program executes that line of instruction
Judging by your comments, you are interested in when to use one or the other. Note that all types of allocation reserve a computer memory sufficient to fit the value of the variable in it. The size depends on the type of the variable. Statically allocated variables are pined to a place in the memory by the compiler. Automatically allocated variables are pinned to a place in stack by the same compiler. Dynamically allocated variables do not exist before the program starts and do not have any place in memory till they are allocated by 'malloc' or other functions.
All named variables are allocated statically or automatically. Dynamic variables are allocated by the program, but in order to be able to access them, one still needs a named variable, which is a pointer. A pointer is a variable which is big enough to keep an address of another variable. The latter could be allocated dynamically or statically or automatically.
The question is, what to do if your program does not know the number of objects it needs to use during the execution time. For example, what if you read some data from a file and create a dynamic struct, like a list or a tree in your program. You do not know exactly how many members of such a struct you would have. This is the main use for the dynamically allocated variables. You can create as many of them as needed and put all on the list. In the simplest case you only need one named variable which points to the beginning of the list to know about all of the objects on the list.
Another interesting use is when you return a complex struct from a function. If allocated automatically on the stack, it will cease to exist after returning from the function. Dynamically allocated data will be persistent till it is explicitly freed. So, using the dynamic allocation would help here.
There are other uses as well.
In your simple example there is no much difference between both cases. The second requires additional computer operations, call to the 'malloc' function to allocate the memory for your struct. Whether in the first case the memory for the struct is allocated in a static program region defined at the program start up time. Note that the pointer in the second case also allocated statically. It just keeps the address of the memory region for the struct.
Also, as a general rule, the dynamically allocated data should be eventually freed by the 'free' function. You cannot free the static data.
Suppose I am given a (void*) ptr (my basic understanding is, it represents a pointer to a region of unknown data type) passed through the parameter of a function. I am trying to figure out how to access and check if a struct exists a few addresses behind.
To clarify, I am working with a big char array (not malloced) and the ptr passed into the function should point to an address of an unspecified data type within the array. Located before this data is a struct for which I am trying to access.
void function(void *ptr)
{
void *structPtr = (void*)((void*)ptr - sizeof(struct block));
}
Would this work to get me a pointer to the address of the struct located behind the initial "ptr"? And if so, how could I check if it is the block struct?
Apologizes in advance, I know this code is not specific as I am fairly new to the concepts entirely but also, I am in the process of coming up with an algorithm and not yet implementing it. Any references to possibly useful information are much appreciated.
what you are trying to do is risky as you must be sure that you address a correct place in memory. Usually, we add some magic number in struct block so that we can test here that we are not going anywhere.
This pattern is generally used in memory allocators,
have a look to https://sourceware.org/glibc/wiki/MallocInternals for an example.
The usual way of writing this is something like:
...function(void *ptr) {
struct block *hdr = (struct block *)ptr - 1;
relying on pointer arithmetic automatically scaling by the size of the pointed at type. As long as all the pointers passed in here were originally created by taking a pointer to a valid struct block and adding 1 to it (to get the memory after it), you should be fine.
I have a structure:
struct generic_attribute{
int current_value;
int previous_value;
};
And a constructor which outputs a pointer to this structure:
struct generic_attribute* construct_generic_attribute(int current_value){
struct generic_attribute *ga_ptr;
ga_ptr = malloc (sizeof (struct generic_attribute));
ga_ptr->current_value = current_value;
ga_ptr->previous_value = 0;
return ga_ptr;
}
Now, in another function, I want to define a pointer and set it to point to the same address as the pointer that the above constructor outputs.
struct tagged_attribute* construct_tagged_attribute(int num_args, int *args){
...
struct generic_attribute* generic = malloc (sizeof(struct generic_attribute));
generic = construct_generic_attribute(args[0]);
...
}
It looks to me that what I am doing here is this:
1) I define a pointer "generic" and allocate a memory chunk to hold an instance of generic_attribute structure.
2) I call a function construct_generic_attribute within which, the program once again allocates a memory chunk of size of a generic_attribute structure. It outputs a pointer to this memory chunk.
3) In construct_tagged_attribute I set "generic" pointer equal to the pointer output by the construct_generic_attribute function, so now both of them point to the same memory slot.
However, it appears that I am allocating twice as much memory as I need to allocate.
Is there a way for me to allocate memory only once without getting a segmentation fault for failing to allocate space for "generic" pointer? Alternatively, am I misunderstanding what is happening in this code?
struct generic_attribute* generic = construct_generic_attribute(args[0]);
Should do the trick. Pointer variable is just that, a variable. You can trade pointer values around just like numbers.
Yes, you're misunderstanding, but I can't quite figure out what you think is happening to explain how it's wrong.
struct generic_attribute *generic = construct_generic_attribute(args[0]); a pointer is a kind of value. If you assign a pointer to another, you get two pointers to the same thing, without any allocation of memory. Since C doesn't manage memory for you, it's up to you to make sure that any object that's allocated is freed exactly once, and that you don't try to use pointers to an object after it's been freed.
Here
struct generic_attribute* generic = malloc (sizeof(struct generic_attribute));
you allocate a memory block, big enough to keep a generic_attribute structure, then store a pointer to that structure (technically: an address of the block) in the generic variable. Note: you do not initialize the structure members.
Then in
generic = construct_generic_attribute(args[0]);
you call a function, which internally allocates (another) block of memory and initializes it and returns a pointer to it (which was stored in a ga_ptr variable during the function execution). The pointer returned is then assigned to the generic variable, overwriting the value stored there by a previous instruction. Consequently you loose an access to the first allocated structure.
EDIT
I'm afraid I do not quite understand what you're trying to achieve. If you want two pointers to the same structure, just declarega1 and assign it a pointer to the created structure:
struct generic_attribute *ga1 = construct_generic_attribute(args[0]);
then make a copy of the pointer:
struct generic_attribute *ga2 = ga1;
I'm new to C and have been working on getting pointers and such down. I'm working on an exercise in school in which we're supposed to be malloc'ing all of our required memory, including mutexes. As far as I am aware, malloc always returns a pointer to some memory (unless it fails). If this is the case, how would you malloc for something like a mutex, which is fundamentally not a pointer?
In the assignment, it's stated pretty flatly that we have to do this for mutexes too, but I can't find how to do this anywhere.
Lastly, I don't want anyone to worry about "giving me the answer", as that's not really the problem I'm being assigned; rather, this is a necessary requisite to the memory monitoring we're supposed to be doing; I'm just not sure what the proper syntax is supposed to be.
You can have pointers to any type.
Your mutex is probably defined like that: struct mutex_t {..}. If so, you can have a pointer to it: struct mutex_t *my_mutex which you can later use to store pointer returned by malloc. See this example:
struct mutex_t *my_mutex;
my_mutex = malloc(sizeof(struct mutex_t));
The second line initiates my_mutex to pointer pointing to some memory of size of your mutex struct. Now, most probably the library you are using defines functions to initialize it like void mutex_init(struct mutex_t*), which you can use to actually construct mutex in memory reserved by malloc.
malloc will ALWAYS give you a pointer to memory to use for an object. But if you're used to using objects automatically allocated on the stack, you can always use a pointer and then dereference as necessary.
For example, if you're used to:
mutex_t bar;
lock_mutex(bar);
unlock_mutex(bar);
Instead, you would do
mutex_t *bar = malloc(sizeof(mutex_t));
lock_mutex(*bar);
unlock_mutex(*bar);
free(bar);
However, all the threading libraries I'm familiar with C expect pointer arguments. For example, with pthreads, you might do something like
pthread_mutex_t foo;
pthread_mutex_init(&foo, NULL);
pthread_mutex_lock(&foo);
pthread_mutex_destroy(&foo);
The &foo means you're actually already passing a pointer to foo, so if foo was a pointer, simply remove the reference operator.
pthread_mutex_t *foo = malloc(sizeof(pthread_mutex_t));
pthread_mutex_init(foo, NULL);
pthread_mutex_lock(foo);
pthread_mutex_unlock(foo);
pthread_mutex_destroy(foo);
free(foo);
As far as I am aware, malloc always returns a pointer to some memory (unless it fails). If this is the case, how would you malloc for something like a mutex, which is fundamentally not a pointer?
pointers are pointers to things; a mutex, like any other object, can have a pointer to it. If you have some type mutex_t then there's a type mutex_t*. So,
mutex_t* pmutex = malloc(sizeof *pmutex);
allocates the number of bytes required for a mutex and stores a pointer to those bytes in pmutex. Note how this is different from
mutex_t mutex;
Here, mutex is a mutex_t, not a pointer to one. Access to fields of the mutex would be
pmutex->field
mutex.field
To refer to a whole mutex_t:
*pmutex
mutex
To refer to the address of the mutex_t:
pmutex
&mutex
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.