成员结构的值在作为指针传递给函数后丢失
Values of member struct get lost after being passed to a function as a pointer
总结:
我遇到一个问题,我在结构中的指针在传递给函数后被随机化。
所以我传递了指针为 in-tact 的原始结构(我在那里检查过它并且它有效),但是在传递给函数之后,声明的指针不再起作用。指针指向相同的地址,但结构的内容丢失并随机化,没有任何先前数据仍然存在。
注意:所有像 ph_ReturnTypeInt 这样的签名都只是专门的类型。我在其中添加了额外数据的结构,在这种情况下这些数据无关紧要,除了函数指针签名
注意 2:由于有很多代码可能并不重要,所以我试图解释什么是什么,但如果您需要,请在此处 GitHub link。否则谢谢你,如果你能帮助我^^
正在调用的函数:
/// 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;
}
“丢失”其 child_ctx 指针的结构:
/// 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;
returns结构的函数:
/// 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;
}
主要功能:
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);
}
作为函数指针传递的函数:
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;
}
最后是额外的上下文(主文件和另一个header带有签名,应该不会有太大影响):
// 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
主线:
/* Wrapping the wrapped context */
DecorateFunc_WrapContext deco_ctx2 = DecorateFunc(deco_ctx);
deco_ctx2.wrapper_func(&deco_ctx2, 20);
在 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
};
}
}
在 <-- this line
link 时对 child_ctx
的赋值 new_ctx 到 main() 中 deco_ctx
的临时副本。由于您按值传递结构,编译器在堆栈上构造了它的临时副本,然后(可能)在函数完成后重新使用堆栈的该区域。您的 link (.child_ctx
) 现在悬空了。
您需要传递 new_ctx 的地址,调整 DecorateFunc
以接受一个指针,将 .child_ctx
分配给该指针,并调整您的测试以处理指针,它有效.
总结:
我遇到一个问题,我在结构中的指针在传递给函数后被随机化。
所以我传递了指针为 in-tact 的原始结构(我在那里检查过它并且它有效),但是在传递给函数之后,声明的指针不再起作用。指针指向相同的地址,但结构的内容丢失并随机化,没有任何先前数据仍然存在。
注意:所有像 ph_ReturnTypeInt 这样的签名都只是专门的类型。我在其中添加了额外数据的结构,在这种情况下这些数据无关紧要,除了函数指针签名
注意 2:由于有很多代码可能并不重要,所以我试图解释什么是什么,但如果您需要,请在此处 GitHub link。否则谢谢你,如果你能帮助我^^
正在调用的函数:
/// 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;
}
“丢失”其 child_ctx 指针的结构:
/// 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;
returns结构的函数:
/// 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;
}
主要功能:
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);
}
作为函数指针传递的函数:
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;
}
最后是额外的上下文(主文件和另一个header带有签名,应该不会有太大影响):
// 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
主线:
/* Wrapping the wrapped context */
DecorateFunc_WrapContext deco_ctx2 = DecorateFunc(deco_ctx);
deco_ctx2.wrapper_func(&deco_ctx2, 20);
在 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
};
}
}
在 <-- this line
link 时对 child_ctx
的赋值 new_ctx 到 main() 中 deco_ctx
的临时副本。由于您按值传递结构,编译器在堆栈上构造了它的临时副本,然后(可能)在函数完成后重新使用堆栈的该区域。您的 link (.child_ctx
) 现在悬空了。
您需要传递 new_ctx 的地址,调整 DecorateFunc
以接受一个指针,将 .child_ctx
分配给该指针,并调整您的测试以处理指针,它有效.