简体   繁体   English

成员结构的值在作为指针传递给 function 后丢失

[英]Values of member struct get lost after being passed to a function as a pointer

Summary:概括:

I have an issue where my pointer inside a struct gets randomised after being passed to the function.我有一个问题,我的结构内的指针在传递给 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.所以我传递了原始结构,指针保持不变(我在那里检查它并且它工作),但是在传递给 function 后,所述指针不再工作。 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.注意:所有像 ph_ReturnTypeInt 这样的签名都只是专门的类型。 structs where I added additional data which don't matter much in this case, except for the function pointer signatures我添加了在这种情况下无关紧要的其他数据的结构,除了 function 指针签名

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.注意 2:由于有很多代码可能并不重要,我试图解释什么是什么,但如果你需要的话,这里是 GitHub 链接 Else thank you if you can help me ^^如果你能帮助我,谢谢你^^

The function being called: function 被称为:

/// 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: “丢失”其 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;

Function that returns the struct: Function 返回结构:

/// 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:主要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: function 作为 function 指针传递:

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):最后是附加上下文(主文件和其他 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

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().<-- this line处对 child_ctx 的分配将child_ctx链接到 main() 中deco_ctx的临时副本。 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.由于您按值传递结构,因此编译器在堆栈上构建了它的临时副本,然后(可能)在 function 完成后重新使用堆栈的该区域。 Your link ( .child_ctx ) is now dangling.您的链接 ( .child_ctx ) 现在悬空。

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 .您需要传递 new_ctx 的地址,调整DecorateFunc以接受指针,将.child_ctx分配给该指针,并调整您的测试以处理指针,它可以工作

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM