簡體   English   中英

成員結構的值在作為指針傳遞給 function 后丟失

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

概括:

我有一個問題,我的結構內的指針在傳遞給 function 后被隨機化。

所以我傳遞了原始結構,指針保持不變(我在那里檢查它並且它工作),但是在傳遞給 function 后,所述指針不再工作。 指針指向相同的地址,但結構的內容丟失並隨機化,沒有任何先前的數據仍然存在。

注意:所有像 ph_ReturnTypeInt 這樣的簽名都只是專門的類型。 我添加了在這種情況下無關緊要的其他數據的結構,除了 function 指針簽名

注意 2:由於有很多代碼可能並不重要,我試圖解釋什么是什么,但如果你需要的話,這里是 GitHub 鏈接 如果你能幫助我,謝謝你^^

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;
}

“丟失”其 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 返回結構:

/// 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;
}

主要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);
}

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;
}

最后是附加上下文(主文件和其他 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_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 的分配將child_ctx鏈接到 main() 中deco_ctx的臨時副本。 由於您按值傳遞結構,因此編譯器在堆棧上構建了它的臨時副本,然后(可能)在 function 完成后重新使用堆棧的該區域。 您的鏈接 ( .child_ctx ) 現在懸空。

您需要傳遞 new_ctx 的地址,調整DecorateFunc以接受指針,將.child_ctx分配給該指針,並調整您的測試以處理指針,它可以工作

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM