weird issue using struct pointer in c - c

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);

Related

In C, I understand why not to return the address of a local variable in a pointer returning function, how can I fix it though?

I have the following code:
int* foo(){
int x = 15;
return &x; }
Which I understand why not to do since the local variable address gets erased from the stack after the function finishes and it becomes a dangling pointer. The question is, how do I not make it a dangling variable without making x a static variable
The blessed ways are:
return a value and not an address
int foo(){
int x = 15;
return x;
}
have the caller to provide an address
int *foo(int *x) {
*x = 15;
return x;
}
or
void foo(int *x) {
*x = 15;
}
Return dynamic (allocated) memory:
int *foo() {
int *x = malloc(sizeof(*x));
// should test valid allocation but omitted for brievety
*x = 15;
return x;
}
Beware, the caller will take ownership or the allocated memory and is responsable to free it later.
Either allocate memory from the heap inside the function
int *f() {
int *foo = malloc(sizeof(int));
if(!foo) {
// Do appropriate error handling here
}
return foo;
}
Don't forget to free it at some point though.
Or you pass in a pointer to a variable living outside the function:
void f(int *foo) {
*foo = 42;
}
void g() {
int goo;
f(&goo);
}

How to store int pointer in void*?

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;
}

Getting seg fault when using malloc with double pointer

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;

what is causing segmentation fault in c code, dynamic allocation accross functions

I am trying to have dynamically allocate arrays of structures and perform operations on them but i keep running into segmentation faults. could someone help me out?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void *malloc(size_t size);
typedef struct {
double x;
double y;
} coords;
struct figure {
char fig_name[128];
int coordcount, size_tracker;
coords *pointer;
} fig;
void init_fig(int n, struct figure **point)
{
printf("%u\n", sizeof(coords));
point[n]->pointer = malloc(sizeof(coords) * 20); <-------SEGFAULT
if (point[n]->pointer == NULL){
exit(-1);
}
point[n]->pointer[19].x = 2;
point[n]->pointer[0].x = 1;
point[n]->pointer[0].y = 2;
point[n]->pointer[7].x = 100;
}
int main()
{
int numfigs = 1;
struct figure * point;
point = malloc(sizeof(struct figure) * 16);
point = &fig;
point[1].coordcount = 1;
init_fig(numfigs, &point);
return 0;
}
I labelled where the first seg fault occurs, (used ddd). what i dont get is that i can manipulate point[1] in main but not in any other function.
I agree with #Maxim Skurydin.
Nevertheless I'd like to explain your mistake in some more details.
Reading your init_fig one assumes that the parameter you pass struct figure **point - is actually array of pointers to struct figure. And this function accesses its n'th element.
However in your main you do something else. You allocate an array of struct figure, and your point variable points to its head. Then you take the address of this local variable and call your init_fig.
Here's the problem. init_fig assumes that you pass it an array of pointers, whereas actually this "array" consists of a single element only: the local point variable declared in main.
EDIT:
How to do this properly.
Leave main intact, fix init_fig.
This means that actually there's an array of figure structs. Means - a single memory block, interpreted as an array of consequent structs.
void init_fig(int n, struct figure *point)
{
printf("%u\n", sizeof(coords));
point[n].pointer = malloc(sizeof(coords) * 20); <-------SEGFAULT
if (point[n].pointer == NULL){
exit(-1);
}
point[n].pointer[19].x = 2;
point[n].pointer[0].x = 1;
point[n].pointer[0].y = 2;
point[n].pointer[7].x = 100;
}
Leave init_fig intact. Fix main.
This means that we actually should allocate an array of pointers, every such a pointer should point to an allocated point structure.
int main()
{
int numfigs = 1;
struct figure ** point;
point = malloc(sizeof(struct figure*) * 16);
for (i = 0; i < 16; i++)
point[i] = malloc(sizeof(struct figure));
point[1].coordcount = 1;
init_fig(numfigs, &point);
return 0;
}
You allocate memory and store the pointer in point but then you forget that pointer when you assign &fig to it.
point = malloc(sizeof(struct figure) * 16);
point = &fig;
So, you are essentially trying to write fig[1], that does not make sense.
struct figure * point;
point = malloc(sizeof(struct figure) * 16);
here point is pointer pointing to memory of 16 structures in heap
but in the next line you have done this
point = &fig;
so its memory leak and also point is not pointing to that allocated region anymore
and also init_fig should be like this
void init_fig(int n, struct figure **point)
It's the problem of segfault
Eliminate this line point = &fig;
and modify the function:
void init_fig(int n, struct figure *point)
{
...
point[n].pointer = (coords*) malloc(sizeof(coords) * 20);
...
}
since you should pass an array of structs and not an array of pointers.
Also, add a third parameter to the init_fig function so you can pass the size of the array of points that you want to create. Like :
void init_fig(int n, struct figure *point, int size)
{
...
point[n].pointer = (coords*) malloc(sizeof(coords) * size);
...
}
Therefore, making the function more reusable.
Modify also the call to that function:
init_fig(numfigs, &point); to init_fig(numfigs, point);

Returning this pointer from a function

I am trying to return a pointer from a function. But I am getting a segmentation fault. Someone please tell what is wrong with the code
#include <stdio.h>
int *fun();
main()
{
int *ptr;
ptr = fun();
printf("%d", *ptr);
}
int *fun()
{
int *point;
*point = 12;
return point;
}
Allocate memory before using the pointer. If you don't allocate memory *point = 12 is undefined behavior.
int *fun()
{
int *point = malloc(sizeof *point); /* Mandatory. */
*point=12;
return point;
}
Also your printf is wrong. You need to dereference (*) the pointer.
printf("%d", *ptr);
^
Although returning a pointer to a local object is bad practice, it didn't cause the kaboom here. Here's why you got a segfault:
int *fun()
{
int *point;
*point=12; <<<<<< your program crashed here.
return point;
}
The local pointer goes out of scope, but the real issue is dereferencing a pointer that was never initialized. What is the value of point? Who knows. If the value did not map to a valid memory location, you will get a SEGFAULT. If by luck it mapped to something valid, then you just corrupted memory by overwriting that place with your assignment to 12.
Since the pointer returned was immediately used, in this case you could get away with returning a local pointer. However, it is bad practice because if that pointer was reused after another function call reused that memory in the stack, the behavior of the program would be undefined.
int *fun()
{
int point;
point = 12;
return (&point);
}
or almost identically:
int *fun()
{
int point;
int *point_ptr;
point_ptr = &point;
*point_ptr = 12;
return (point_ptr);
}
Another bad practice but safer method would be to declare the integer value as a static variable, and it would then not be on the stack and would be safe from being used by another function:
int *fun()
{
static int point;
int *point_ptr;
point_ptr = &point;
*point_ptr = 12;
return (point_ptr);
}
or
int *fun()
{
static int point;
point = 12;
return (&point);
}
As others have mentioned, the "right" way to do this would be to allocate memory on the heap, via malloc.
It is not allocating memory at assignment of value 12 to integer pointer. Therefore it crashes, because it's not finding any memory.
You can try this:
#include<stdio.h>
#include<stdlib.h>
int *fun();
int main()
{
int *ptr;
ptr=fun();
printf("\n\t\t%d\n",*ptr);
}
int *fun()
{
int ptr;
ptr=12;
return(&ptr);
}
To my knowledge the use of the keyword new, does relatively the same thing as malloc(sizeof identifier). The code below demonstrates how to use the keyword new.
void main(void){
int* test;
test = tester();
printf("%d",*test);
system("pause");
return;
}
int* tester(void){
int *retMe;
retMe = new int;//<----Here retMe is getting malloc for integer type
*retMe = 12;<---- Initializes retMe... Note * dereferences retMe
return retMe;
}

Resources