Reputation: 13
Summary:
I have an issue where my pointer inside a struct gets randomised after being passed to the function.
So I pass the original struct with the pointer being in-tact (I checked it there and it works), but after being passed to the function the stated pointer doesn't work anymore. The pointer points to the same address, but the content of the struct is lost and randomised without any prior data still existing.
Note: All of the signatures like ph_ReturnTypeInt are just specialised types aka. structs where I added additional data which don't matter much in this case, except for the function pointer signatures
Note 2: Since it's a lot of code that might be unimportant I tried to explain what is what, but here the GitHub link if you need it. Else thank you if you can help me ^^
The function being called:
/// Defined wrapper for the function
/// @param call_ctx Call Context for the wrapper
/// @param x Example for how a user argument could look like
ph_ReturnTypeInt DecorateFunc_Wrapper(DecorateFunc_WrapContext *call_ctx, int x)
{
printf("Called wrapper\n");
// ----> Compiler generated ---->
ph_ReturnTypeInt call_r;
// Child Context is null -> Reached lowest level of wrapping
if (!call_ctx->child_ctx && !call_ctx->has_child_ctx)
{
// Calling the wrapped function
call_r = call_ctx->wrapped_func(x);
}
else
{
// Passing the context down one level to the other function
call_r = (*call_ctx->child_ctx).wrapper_func(call_ctx->child_ctx, x);
}
int local_r = call_r.actual_value;
// <---- Compiler generated <----
printf("Finished function call\n");
// ----> Compiler generated ---->
ph_ReturnTypeInt func_r = {
.base.is_exception = false,
.base.is_null = false,
.actual_value = local_r
};
// <---- Compiler generated <----
return func_r;
}
The struct which "loses" its child_ctx pointer:
/// Context for the DecorateFunc Decorator. Contains a child_ctx element to point to a child if it exists. Contains
/// a wrapper function and wrapped function. The wrapped function should be NULL if child_ctx is populated.
typedef struct DecorateFunc_WrapContext {
bool has_child_ctx;
ph_DecoType_Int_Int wrapped_func;
DecorateFunc_Wrapper_Type wrapper_func;
DecorateFunc_WrapContext *child_ctx;
} DecorateFunc_WrapContext;
Function that returns the struct:
/// Decorates a function and returns a struct containing the func and the wrapper specified for this decorator.
/// @param passable Passable struct that can either contain a function or an initialised wrapped struct that should
/// be wrapped again. In both cases the types must match with the target of the decorator to correctly pass
/// the arguments.
DecorateFunc_WrapContext DecorateFunc(DecorateFunc_WrapContext ctx)
{
printf("Called decorator\n");
// ----> Compiler generated ---->
DecorateFunc_WrapContext new_ctx;
// Child Context is null -> Reached lowest level of wrapping / The function does not have any more wrapping
if (!ctx.child_ctx && !ctx.has_child_ctx && !ctx.wrapper_func)
{
new_ctx = (DecorateFunc_WrapContext) {
.has_child_ctx = false,
.wrapper_func = DecorateFunc_Wrapper,
.wrapped_func = ctx.wrapped_func,
.child_ctx = NULL
};
}
else
{
// Creating a new context and passing the context as a child
new_ctx = (DecorateFunc_WrapContext) {
.has_child_ctx = true,
.wrapper_func = DecorateFunc_Wrapper,
.child_ctx = &ctx,
};
}
// <---- Compiler generated <----
return new_ctx;
}
The main function:
int main()
{
DecorateFunc_WrapContext p;
p = (DecorateFunc_WrapContext) { .wrapped_func = &main_func };
DecorateFunc_WrapContext deco_ctx = DecorateFunc(p);
deco_ctx.wrapper_func(&deco_ctx, 15);
/* Wrapping the wrapped context */
DecorateFunc_WrapContext deco_ctx2 = DecorateFunc(deco_ctx);
deco_ctx2.wrapper_func(&deco_ctx2, 20);
}
The function passed as function pointer:
ph_ReturnTypeInt main_func(int x)
{
printf("Called decorated function - Passed argument: %i\n", x);
/* Compiler generated return */
ph_ReturnTypeInt r = {
.base.is_exception = false,
.base.is_null = false,
.actual_value = 3
};
return r;
}
And lastly the additional context (the main file and the other header with the signatures, which shouldn't have a big influence):
// Used content of the header. Other content is just declarations etc.
/* Undefined Base Return which serves as the base for all ReturnTypes */
typedef struct ph_UndefBaseReturn {
bool is_exception;
const char* exception;
const char* traceback;
bool is_null;
} ph_UndefBaseReturn;
/* Para-C Return of Type int. Compiler-Generated */
typedef struct ph_ReturnTypeInt {
ph_UndefBaseReturn base;
int actual_value;
} ph_ReturnTypeInt;
/* Decorator Return Types - Compiler-Generated */
typedef ph_ReturnTypeInt (*ph_DecoType_Int_Int)(int);
// At the top of the main file
typedef struct DecorateFunc_WrapContext DecorateFunc_WrapContext;
/// Signature of the wrapper - Returns int and contains as parameters a int return function and an int
/// This type will be automatically generated for any wrapper, but only used in the decorator for correctly creating
/// the struct which will store the wrapper and wrapped function.
typedef ph_ReturnTypeInt (*DecorateFunc_Wrapper_Type)(DecorateFunc_WrapContext*, int); // R: int - P: struct, int
Upvotes: 0
Views: 538
Reputation: 10435
In main:
/* Wrapping the wrapped context */
DecorateFunc_WrapContext deco_ctx2 = DecorateFunc(deco_ctx);
deco_ctx2.wrapper_func(&deco_ctx2, 20);
In DecorateFunc:
DecorateFunc_WrapContext DecorateFunc(DecorateFunc_WrapContext ctx)
{
...
{
// Creating a new context and passing the context as a child
new_ctx = (DecorateFunc_WrapContext) {
.has_child_ctx = true,
.wrapper_func = DecorateFunc_Wrapper,
.child_ctx = &ctx, // <-- this line
};
}
}
The assignment to child_ctx
at <-- this line
links new_ctx to a temporary copy of deco_ctx
in main(). Since you passed the structure by value, the compiler constructed a temporary copy of it on the stack, then (likely) re-used that area of the stack once the function completed. Your link (.child_ctx
) is now dangling.
You need to pass the addresss of new_ctx, adjust DecorateFunc
to accept a pointer, assign .child_ctx
to that pointer, and adjust your tests to deal with a pointer, it works.
Upvotes: 1