I'm using something like this to allocate memory with a function (in C)
void myfunction(struct mystruct** ss) {
// some code
*ss = malloc( 1024 * sizeof (struct mystruct) );
// some code
}
int main()
{
struct mystruct **x;
*x = NULL;
myfunction(x);
return 0;
}
but I'm getting seg fault. What is wrong with this code?
After struct mystruct **x;, the variable x is uninitialized. It is illegal to read from it as your program does in *x = NULL;.
You may have wanted to write:
int main()
{
struct mystruct *x;
x = NULL;
myfunction(&x);
return 0;
}
But it is impossible to be sure, as your program does not do anything meaningful.
Note that x = NULL; is unnecessary anyway: x will be initialized inside myfunction().
you never make any storage for the underlying pointer, there is storage for the ** and the object but not the *...
struct mystruct **x,*y;
x = &y;
myfunction(x);
return 0;
Related
So when I pass a data type like a struct to assign some memory to it I find that the pointer doesn't change within the main scope. This further becomes a problem when I try to free the memory but obviously if its using the original pointer it will be pointing at the stack address.
void allocate(int *value){
value = malloc(10 * sizeof(int));
}
int main(){
int val2;
allocate(&val2);
free(&val2);
return 0;
}
I can fix this by using a double pointer to be passed into the allocate function but some course work I'm doing requires to only pass a pointer and I cant get it to update the pointer when it returns to main. I have looked around for a while but cant find a straight forward answer, I feel like my coursework is wrong but that might be my lack of understanding.
The requirement to "only pass a pointer" seems contrived, and you could argue that a pointer to pointer (not a "double pointer") is a pointer, but perhaps you could use void * to punch a hole in the type system. Or use a struct:
#include <stdlib.h>
#include <stdio.h>
struct intbuffer {
int *d;
size_t cap;
};
void *
xmalloc(size_t s)
{
void *r = malloc(s);
if( r == NULL ){
perror("malloc");
exit(1);
}
return r;
}
void
allocate(void *p, size_t s)
{
*(int **)p = xmalloc(s * sizeof(int));
}
void
allocate2(struct intbuffer *p)
{
p->d = xmalloc(p->cap * sizeof *p->d);
}
int
main(void)
{
int *val2;
struct intbuffer v;
allocate(&val2, 10);
free(val2);
v.cap = 10; /* Horrible api!! */
allocate2(&v);
free(v.d);
return 0;
}
Note that setting the capacity in the struct prior to making the call to allocate is a violation of many principles of software design, but this whole thing is absurdly contrived due to the bizarre artificial limitations.
There are not enough *'s in each place, but you will have to figure out what that means.
void allocate(int** value){
*value = malloc(10 * sizeof(int));
}
int main(){
int* val2;
allocate(&val2);
free(val2);
return 0;
}
I have an issue with pointers to struct that have members that are pointers to struct too.
Browsing the suggested similar questions I found out this:
Accessing elements within a pointer of a struct inside another pointer to a struct
where people suggest to pay attention to allocation memory of the structure.
I think this is done correctly in my code.
typedef struct {
int id_vec;
float *vec_value;
} Vector;
typedef struct cluster{
int id_cluster;
float *centroid;
Vector *patternInCluster;
} Cluster;
int main(void){
Cluster *cluster_ptr= malloc(3 * sizeof(Cluster));
if (cluster_ptr==NULL){
printf("NULL");
}
cluster_ptr->patternInCluster=malloc(2 * sizeof(Vector *));
if (cluster_ptr->patternInCluster==NULL){
printf("NULL");
cluster_ptr->patternInCluster=NULL;
}
float p1[3]={0.0f,1.0f,2.0f};
Vector *somePattern=malloc(2 * sizeof(Vector));
somePattern[0].id_vec=1;
somePattern[0].vec_value=p1;
somePattern[1].id_vec=2;
somePattern[1].vec_value=p1;
}
Then I expect that this statement works:
cluster_ptr[1].patternInCluster[1]=somePattern[1];
But it compiles and produces a Segmentation Fault.
Unexpectedly, the following statement doesn't get errors:
cluster_ptr[0].patternInCluster[1]=somePattern[1];
and a test show me correct result(somePattern[1] id and value)
I tried to debug with gdb but I only can see this:
Program received signal SIGSEGV, Segmentation fault.
0x00005555555547fe in main () at test_struct.c:36
36 cluster_ptr[1].patternInCluster[1]=somePattern[1];
Am I missing some allocation mistakes?
It's because you're not populating things fully.
This line
cluster_ptr->patternInCluster=malloc(2 * sizeof(Vector *));
is the same as saying
cluster_ptr[0].patternInCluster=malloc(2 * sizeof(Vector *));
and really given that cluster_ptr has been allocated as 3 Cluster it would be more clearer in your code to do the latter.
Since cluster_ptr[1].patternInCluster hasn't been given a value, trying to dereference it will lead to undefined behaviour but more likely will result in a segmentation fault.
You do not allocate enough memory:
cluster_ptr->patternInCluster=malloc(2 * sizeof(Vector *));
With patternInCluster being of type Vector *, you should allocate memory to hold elements of type Vector, not Vector*.
cluster_ptr->patternInCluster=malloc(2 * sizeof(Vector));
Your problem is NOT accessing the pointer inside the struct. Your problem is how you are using malloc().
When you have one pointer, you malloc only once:
int *pointer = (int* )malloc(sizeof(int));
*pointer = 1;
printf("*pointer:%d\n", *pointer);
When you have pointer-to-pointer, you malloc() once for the **pointer_to_pointer, but you also have to malloc() once for the *pointer_to_pointer:
int** pointer_to_pointer = (int** )malloc(sizeof(int*));
*pointer_to_pointer = (int* )malloc(sizeof(int));
**pointer_to_pointer = 2;
printf("**pointer:%d\n", **pointer_to_pointer);
And if you have more than one pointer, at the location pointed to by **pointer_to_pointer, you need a for loop to assign memory to every one of those *pointer_to_pointers.
for (unsigned int i = 0; i < 3; i++)
{
*(pointer_to_pointer + i*sizeof(int)) = (int* )malloc(sizeof(int));
}
**(pointer_to_pointer + sizeof(int)) = 3;
**(pointer_to_pointer + 2UL*sizeof(int)) = 4;
printf("**(pointer_to_pointer + sizeof(int):%d\n", **(pointer_to_pointer + sizeof(int)));
printf("**(pointer_to_pointer + 2UL*sizeof(int):%d\n", **(pointer_to_pointer + 2UL*sizeof(int)));
You are mistaken to think that Cluster *cluster_ptr= malloc(3 * sizeof(Cluster)); will automatically/magically assign memory for Cluster[0] and Cluster[1] and Cluster[2].
Your statement actually assigns memory only for Cluster[0], but big enough for 3 Clusters.
So the the modified code will look like this:
#include <string.h>
#include <stdio.h>
#include <malloc.h>
typedef struct {
int id_vec;
float *vec_value;
} Vector;
typedef struct cluster{
int id_cluster;
float *centroid;
Vector **patternInCluster;
} Cluster;
int main(void){
Cluster **cluster_ptr = (Cluster **)malloc(sizeof(Cluster*));
for (long unsigned int i = 0; i < 3; i++) {
cluster_ptr[i] = (Cluster *)malloc(sizeof(Cluster));
if (cluster_ptr[i]==NULL){
printf("NULL");
}
cluster_ptr[i]->patternInCluster = (Vector **) malloc(sizeof(Vector*));
for (long unsigned int j = 0; j < 3; j++) {
(*cluster_ptr)->patternInCluster[j] = (Vector *) malloc(sizeof(Vector));
if ((*cluster_ptr)->patternInCluster[j]==NULL){
printf("NULL");
(*cluster_ptr)->patternInCluster[j]=NULL;
}
}
}
float p1[3]={0.0f,1.0f,2.0f};
Vector *somePattern= (Vector *) malloc(sizeof(Vector));
somePattern[0].id_vec=1;
somePattern[0].vec_value=p1;
somePattern[1].id_vec=2;
somePattern[1].vec_value=p1;
cluster_ptr[1]->patternInCluster[1] = &somePattern[0];
cluster_ptr[0]->patternInCluster[1] = &somePattern[1];
cluster_ptr[1]->patternInCluster[0] = &somePattern[1];
cluster_ptr[2]->patternInCluster[1] = &somePattern[0];
printf("%d\n", cluster_ptr[1]->patternInCluster[1]->id_vec);
printf("%d\n", cluster_ptr[0]->patternInCluster[1]->id_vec);
printf("%d\n", cluster_ptr[1]->patternInCluster[0]->id_vec);
printf("%d\n", cluster_ptr[2]->patternInCluster[1]->id_vec);
return 0;
}
On my system, I just compiled and it builds and runs error-free.
Scenario is as follows:
typedef struct a {
void* val;
} a_t;
void fun (void** val)
{
int a = 5;
*val = &a;
}
a_t *x;
x = malloc (sizeof *x);
fun (&x->val);
printf ("%d", *((int*)(x->val)));
I would expect, that the x->val is of type void* (when used in printf()). How can I get back that int value I stored into it?
The problem is in fun
If you expect 5 on STDOUT than this function should look like this:
void fun (void** val)
{
int *a = malloc(sizeof(int));
*a = 5;
*val = a;
}
You should not return pointer to automatic variable because it's allocated on stack and deferred after function executions. To get more info look at this answer
The problem is that the pointer is set to a local variable. So when the function terminates, it's memory will be de-allocated, thus the pointer will be set to garbage (it will become a dangling pointer as Hans suggested).
So if you are lucky, the printf() will print garbage, if not, then it will print 5.
A quick fix would be to add the static keyword to int a, which make it not to be de-allocated when the function gets terminated.
void fun(void** val) {
static int a = 5;
*val = &a;
}
However this is not very flexible, because all the instances of fun() will have the same variable a.
Or you could dynamically allocate memory like this:
void fun(void** val) {
int *a = malloc(sizeof(int));
*a = 5;
*val = a;
}
Don't forget to free your memory like this:
a_t *x;
x = malloc (sizeof *x);
fun (&x->val);
printf ("%d", *((int*)(x->val)));
free(x->val); // this has to go first
free(x);
return 0;
}
I usually make myself a struct and I allocate memory for the struct and sometimes for buffers inside the struct. Like so:
typedef struct A
{
char *buffer;
int size;
} A;
Then when I malloc for the struct I do this. (I learned not to cast the malloc return here on SO.)
X
A *a = malloc(sizeof(a));
a->buffer = malloc(10*sizeof(a->buffer));
What is the difference between X and Y this?
Y
A *a = malloc(sizeof(*a));
a->buffer = malloc(10*sizeof(a->buffer));
They seem to be doing the same thing.
Neither is correct, the second one doesn't even compile.
You want either of these:
A * a = malloc(sizeof(A)); // repeat the type
// or:
A * a = malloc(sizeof *a); // be smart
Then:
a->size = 213;
a->buffer = malloc(a->size);
you should typecast it (A *) because calloc or malloc return void *.
A *a=(a*)malloc(sizeof(A));
suppose you want to allocate memory for buffer for 10 characters
a->buffer=(char *)malloc(sizeof(char)*10);
Ok, so i'm totally new to structs in c, and i have a problem that seems very strange to me.
When passing a simple struct to a function using it's pointer, the struct automatically takes one of the other arguments of that function as it's new data. I have no idea why this would happen..
At this moment move_walker() should do nothing at all, right?
typedef struct {
int x,
y;
} walker_t;
walker_t* init_walker(int x, int y) {
walker_t walker;
walker.x = x;
walker.y = y;
walker_t *pointer = malloc(sizeof(walker));
pointer = &walker;
return pointer;
}
int move_walker(walker_t * walker, int direction) {
return 0;
}
walker_t* walker;
walker = init_walker(8,2);
printf("%d %d\n", walker->x, walker->y); //will print '8 2'
move_walker(walker, 3);
printf("%d %d\n", walker->x, walker->y); //will print '0 3'
(I'm pretty sure that it doesnt matter, but this code is actually spreaded over multiple files.)
The problem is that your walker pointer goes to invalid stack memory, because init_walker has a bug: You create a walker_t struct on the stack, then reserve memory with malloc and assign the address of that memory to pointer. So far so good.
However, the line pointer = &walker does not copy the struct from the stack to the new memory, instead it makes pointer point to your struct on the stack! &walker is the address of walker, and you assign that to your pointer. What you probably want to do is to copy the struct. To do that, you have to dereference your pointer:
*pointer = walker
That should make your program work as intended. You can also skip the struct on the stack completely:
walker_t* init_walker(int x, int y) {
walker_t *walker = malloc(sizeof(walker_t));
walker->x = x;
walker->y = y;
return walker;
}
Your init_walker is wrong, because it returns a pointer to a stack-local variable, walker. That variable's memory gets reclaimed once init_walker exits. Your first printf still works, sort of by accident, because your walker variable's value is still untouched on the stack. As soon as you make any function call after that, however, the stack frame of your original init_walker call gets overwritten, and the walker pointer is now pointing to some random garbage.
When you malloc inside init_walker, you're already allocating memory on the heap (which, unlike the stack, lives beyond the lifetime of a stack frame) for your walker_t. So, you should do this instead:
walker_t* init_walker(int x, int y) {
walker_t *pointer = malloc(sizeof(walker_t));
pointer->x = x;
pointer->y = y;
return pointer;
}
You are creating your struct-object on the stack. You'll need to allocate it using
walker_t* init_walker(int x, int y) {
walker_t* walker = malloc(sizeof(walker_t));
...
return walker;
}
With
walker_t *pointer = malloc(sizeof(walker));
pointer = &walker;
you are creating a memory-leak! You assign new memory to *pointer and lose the pointer when you assign &walker to pointer.
walker_t* init_walker(int x, int y) {
walker_t walker;
walker.x = x;
walker.y = y;
walker_t *pointer = malloc(sizeof(walker));
*pointer = walker; /* here was the error. Copy the value not the adress */
return pointer;
}
But it can be simpler:
walker_t* init_walker(int x, int y) {
walker_t *pointer = malloc(sizeof(*pointer));
pointer->x = x;
pointer->y = y;
return pointer;
}
your code is to put it polity 'very strange'.
This will work better...
walker_t *init_walker (int x, int y)
{
walker_t *p_walker = (walker_t *)malloc (sizeof(walker));
if (p_walker != NULL)
{
p_walker->x = x;
p_walker->y = y;
}
return (p_walker);
}
Then call free (walker) when you've finished with them
...or, after a sanity check of the code, you could as well write:
typedef struct
{
int x,
int y;
} walker_t;
void init_walker(walker_t* obj, int x, int y)
{
obj->x = x;
obj->y = y;
}
walker_t walker;
init_walker(&walker, 8,2);