成员结构的值在作为指针传递给函数后丢失
Posted
技术标签:
【中文标题】成员结构的值在作为指针传递给函数后丢失【英文标题】:Values of member struct get lost after being passed to a function as a pointer 【发布时间】:2021-08-17 10:10:54 【问题描述】:总结:
我有一个问题,我在结构中的指针在传递给函数后会随机化。
所以我传递了原始结构,指针保持不变(我在那里检查它并且它工作),但在传递给函数后,所述指针不再工作。指针指向同一个地址,但结构的内容丢失并随机化,没有任何先前的数据仍然存在。
注意:所有像 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;
返回结构的函数:
/// 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;
最后是附加上下文(主文件和其他带有签名的标头,应该不会有太大影响):
// 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
【问题讨论】:
【参考方案1】:主要:
/* Wrapping the wrapped context */
DecorateFunc_WrapContext deco_ctx2 = DecorateFunc(deco_ctx);
deco_ctx2.wrapper_func(&deco_ctx2, 20);
在装饰函数中:
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
对child_ctx
的赋值将new_ctx 链接到main() 中deco_ctx
的临时副本。由于您按值传递结构,因此编译器在堆栈上构建了它的临时副本,然后(可能)在函数完成后重新使用堆栈的该区域。您的链接 (.child_ctx
) 现在悬空。
您需要传递 new_ctx 的地址,调整 DecorateFunc
以接受指针,将 .child_ctx
分配给该指针,并调整您的测试以处理指针,它工作。
【讨论】:
非常感谢 ^^ 这有效并完美解决了问题。以上是关于成员结构的值在作为指针传递给函数后丢失的主要内容,如果未能解决你的问题,请参考以下文章
类成员函数不能作为普通函数地址传递给普通函数指针,几种解决方案