Embedded memory allocation and scope - c

If I want to create a structure initialization functions that return a pointer to the initialized structure members, will the allocated memory to the data array in new_foo still be valid outside the function?
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
typedef struct structure{
char* data;
size_t num;
}foo_t;
foo_t* new_foo(size_t num);
int main(void){
foo_t* foo = new_foo(32);
while(1){;}
}
foo_t* new_foo(size_t num){
foo_t* self;
char temp[num];
self->data = temp;
self->num = num;
return self;
}
I wanted to take a look at the assembly code to see if anything jumped out at me, the only thing that potentially makes me thing memory is still valid is that there are no stack operations associated with
char temp[num];
self->data = temp;
but it's been a while since I had to look at assembly code.
https://godbolt.org/z/5Wx4TY
[EDIT] Modified new_foo
foo_t* new_foo(size_t num){
static foo_t self = {NULL, 0};
char data_array[num];
self.data = temp;
self.num = num;
return &self;
}

The function has undefined behavior.
foo_t* new_foo(size_t num){
foo_t* self;
char temp[num];
self->data = temp;
self->num = num;
return self;
}
For starters the pointer self is not initialized and has indeterminate value.
The variable length array temp is a local variable of the function that will not be alive after exiting the function. So any pointer to it returned from the function will be invalid.

Related

accessing a value in return struct

if you have a function that returns a struct, is it then possible to access on of the internal values in struct that is returned, without having to handling the whole struct.
The code could look something like this;
struct myStruct
{
int value1;
int value2;
};
myStruct functionReturningStruct(void);
....
value2 = functionReturningStruct().value2
if it's possible in anyway, how?
Why don't you test?
#include <stdio.h>
struct myStruct
{
int value1;
int value2;
};
struct myStruct functionReturningStruct(void)
{
return (struct myStruct){10, 20};
}
int main(void)
{
int value = functionReturningStruct().value2;
printf("%d", value);
return 0;
}
It's possible.
Implementations I found use an implicit first argument of functionReturningStruct() which points to the structure, that is temporary allocated by the compiler on call point.
Indeed, it is equivalent to
{
struct myStruct __temp_myStruct;
__actual_functionReturningStruct(&__temp_myStruct);
value2 = __temp_myStruct.value2;
}

It seems like a printf makes my program bug [duplicate]

This question already has answers here:
How to access a local variable from a different function using pointers?
(10 answers)
Closed 5 years ago.
I am learning structures and linked-lists. However I am facing a problem that prevents me from debugging my program's bugs, since it comes, seemingly, from the function printf, which is what I use to debug the program.
The following program works fine:
struct pointer_struct
{
struct new_struct *ptr;
};
struct new_struct
{
int i;
struct new_struct *ptr;
};
void init(struct pointer_struct *pointer, int nb)
{
struct new_struct my_struct;
my_struct.i = nb;
my_struct.ptr = NULL;
pointer->ptr = &my_struct;
}
int main(void)
{
struct pointer_struct pointer;
pointer.ptr = NULL;
init(&pointer, 15);
//printf("pointer.ptr = %p\n", pointer.ptr);
printf("pointer.ptr->i = %d\n", pointer.ptr->i);
}
Output:
pointer.ptr->i = 15
But as soon as I uncomment the commented line, i takes weird values. Here are some examples of outputs:
$./a.out
pointer.ptr = 0x7fffc6bcc650
pointer.ptr->i = -448723664
$./a.out
pointer.ptr = 0x7fffd09ed480
pointer.ptr->i = 1218512176
$./a.out
pointer.ptr = 0x7ffff630fa70
pointer.ptr->i = -1073674960
What is going wrong with printf?
You have an undefined behavior or UB, which is always A Bad Thing™.
void init(struct pointer_struct *pointer, int nb)
{
struct new_struct my_struct;
my_struct.i = nb;
my_struct.ptr = NULL;
pointer->ptr = &my_struct;
} // here my_struct lifetime is finish so pointer->ptr become invalid
int main(void)
{
struct pointer_struct pointer;
pointer.ptr = NULL;
init(&pointer, 15);
printf("pointer.ptr = %p\n", pointer.ptr); // pointer.ptr is not valid so it's UB
printf("pointer.ptr->i = %d\n", pointer.ptr->i); // This is UB too
}
You initialize pointer.ptr with a local variable.
void init(struct pointer_struct *pointer, int nb)
{
struct new_struct my_struct;
my_struct.i = nb;
my_struct.ptr = NULL;
pointer->ptr = &my_struct; // MISTAKE!!! my_struct is on the stack.
// its memory space could be overwritten at
// any time after the function returns.
}
Later, in main
printf("pointer.ptr = %p\n", pointer.ptr); // This call to printf uses the stack,
// and overwrites the space used
// by my_struct
printf("pointer.ptr->i = %d\n", pointer.ptr->i);

Accessing structure in C - functions

I am trying to play around with structures in C and I am stuck at this point. Here's my code:
#include <stdio.h>
void Test(void);
void updateIt(struct Item* ptr);
struct Item
{
double value;
int unitno;
int isTa;
int quant;
int minQuant;
char name[21];
};
int main(void)
{
Test(); // here I am gonna call updateit() function and print
}
void Test(void) {
struct Item I = { 100.10,100,10,110,10,"NAME!" };
updateIt(&I);
}
void updateIt(struct Item* ptr){
struct Item I[0] = 200 // This doesn't work — but why?
}
How do I update values of Item I = { 100.10,100,10,110,10,"NAME!" } to { 200.20,200,20,220,20,"NAME2!"} by accessing values inside the updateIt function?
In the code snippet:
void updateIt(struct Item* ptr){
struct Item I[0] = 200 // This doesn't work — but why?
}
There is no variable I in this scope.
Since you passed the address of the structure through updateIt(&I); in the above function you will have to use the pointer to it.
The pointer variable ptr in the arguments of the function has the address of the structure, which can be used to update the values as :
ptr->structureMember
where structureMember is any member of the structure.
updateIt(struct Item* ptr) accepts pointer ptr of type item; to access fields of structure Item using a pointer, one should use -> operator like below:
void updateIt(struct Item* ptr){
ptr->value = 200.20;
ptr->unitno = 200;
ptr->isTa = 20;
ptr->quant = 220;
ptr->minQuant = 20;
strcpy(ptr->name, "NAME2");
}
You must use the ptr value like
ptr->unitno = 200 and so for every member of the struct

malloc of array in struct passed as argument

I would like to allocate memory for arrays that are members of a struct I need to use, inside a function that takes the struct as an argument.
arg->A.size=(int*) malloc(N*sizeof(int));
will not compile (request for member 'size' is something not a structure.
arg->A->size=(int*) malloc(N*sizeof(int));
will throw a segmentation fault error
Any help will be appreciated.
Here is the code, thanks:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// struct A
struct A {
int dim; // dimensions
int* size; // points per dim array
double* val; // values stored in array
int total; // pow(size,dim)
};
// struct B that uses A
struct B {
int tag;
struct A* A;
};
int function_AB(struct B* B);
int main(void){
struct B B;
function_AB(&B);
return 0;
}
int function_AB(struct B* arg){
int N=10;
arg->tag=99;
printf("tag assigned = %d \n", arg->tag);
arg->A->size=(int*) malloc(N*sizeof(int));
return 0;
}
You simply haven't allocated memory for struct A *A. Before assigning anything to A->size you would first need to do something like
B->A = malloc(sizeof(struct A));
The second case is correct, but crashes because the A inside the B declared in main has not been assigned a value. You probably want something like
struct A A;
struct B B;
B.A = &A;
function_AB(&B);
When you have structure pointer in another structure, first you need to allocate memory for that. then allocate the memory for structure members!
struct B {
int tag;
struct A* A;
};
Here A is a pointer to a structure called A. First allocate memory for this, then allocate memory for the elements of struct A
arg->A = malloc(sizeof(struct A));
then do-
arg->A->size = malloc(N*sizeof(int));
Try the following changes in your int function_AB(struct B* arg)-
int function_AB(struct B* arg){
int N=10;
arg->tag=99;
printf("tag assigned = %d \n", arg->tag);
arg->A = malloc(sizeof(struct A)); // First allocate the memory for struct A* A;
arg->A->size = malloc(N*sizeof(int)); // Allocate the memory for struct A members
arg->A->val = malloc(N*sizeof(double));
// do your stuff
// free the allocated memories here
free(arg->A->size);
free(arg->A->val);
free(arg->A);
return 0;
}
And don't cast the result of malloc()!

Allocate struct on the heap in C [duplicate]

This question already has answers here:
How to malloc inside a function and return pointer in C?
(3 answers)
C: adding element to dynamically allocated array
(3 answers)
Closed 8 years ago.
#include <stdio.h>
#include <stdlib.h>
struct myStruct
{
int number;
};
void
allocateMem(struct myStruct *struct1)
{
struct1 = malloc(sizeof(struct myStruct));
struct1->number = 500;
printf("struct1->number: %d\n", struct1->number);
}
int
main(int argc, char *argv[])
{
struct myStruct *struct1 = NULL;
allocateMem(struct1);
printf("number: %d\n", struct1->number);
return 0;
}
Hello citizens of StackOverflow, I seek your assistance.
What I am trying to do is allocate a struct using heap space rather than stack space; and I am trying to do the allocation inside of a function. No matter how much I mess with this I always get either a segmentation fault or several compiler warnings.
I'm doing something here incorrectly, but I can't figure out what, I've been all over StackOverflow and the general internet trying to find an example or post that relates to my issue but I have not found anything.
If you could tell me what I'm doing wrong, or just point me in the right direction I would be extremely grateful.
Thank you everyone for your quick and accurate replies. You were correct, I needed a pointer to a pointer, my code works now thanks to your help.
In this function,
void
allocateMem(struct myStruct *struct1)
{
struct1 = malloc(sizeof(struct myStruct));
struct1->number = 500;
printf("struct1->number: %d\n", struct1->number);
}
struct1 is passed by value. Any changes you make to it in the function are not visible from the calling function.
A better alternative:
struct myStruct* allocateMem()
{
struct myStruct *struct1 = malloc(sizeof(struct myStruct));
struct1->number = 500;
printf("struct1->number: %d\n", struct1->number);
return struct1;
}
Change the calling function to:
int
main(int argc, char *argv[])
{
struct myStruct *struct1 = allocateMem();
printf("number: %d\n", struct1->number);
// Make sure to free the memory.
free(struct1);
return 0;
}
A pointer is just an integer in reality, when you pass in struct1 to your function since struct1 is null you are just passing in a 0 to your function in reality. that value gets passed on the stack and you do a heap allocation and update the stack value with the new address. but when you return from the function, that value just gets popped of the stack and you have leaked that memory. the value of struct1 in main (which is also on the stack still keeps its value 0(NULL). so you have to pass in a pointer to your pointer if you want to update that value, or what might be easier is just to return the malloc'd pointer from your function.
This is one way you could modify your function to work:
#include <stdio.h>
#include <stdlib.h>
struct myStruct
{
int number;
};
struct myStruct*
allocateMem()
{
struct myStruct* struct1 = malloc(sizeof(struct myStruct));
struct1->number = 500;
printf("struct1->number: %d\n", struct1->number);
return struct1;
}
int
main(int argc, char *argv[])
{
struct myStruct *struct1 = allocateMem();
printf("number: %d\n", struct1->number);
return 0;
}
Because you are changing the struct1 pointer in the method, you need to either return the pointer to the caller, or pass it as a double pointer (address of the caller's pointer), e.g.
Return:
struct myStruct* allocateMem()
{
struct myStruct* struct1 = malloc(sizeof(struct myStruct));
struct1->number = 500;
printf("struct1->number: %d\n", struct1->number);
return struct1;
}
Double pointer:
void allocateMem(struct myStruct **struct1)
{
With the allocation and usage as per #Grijesh's comments below.

Resources