【问题标题】:Wrap alloca function in C在 C 中包装 alloca 函数
【发布时间】:2014-07-20 20:13:23
【问题描述】:

是否可以将 C 函数 alloca 包装成“另一个”? (当然只有宏)

类似:

#define my_alloca(size)                                      \
                             ({                               \
                                   void *ret = alloca(size);  \
                                   my_function(ret);          \
                             ret;})

对此我不太确定,扩展 6.1 Statements and Declarations in Expressions 是否会创建一个新的堆栈框架? (因为大括号,看起来有点像)

编辑:

它做了一些测试:

#define printStackFrameAddr(_fnc)   \
    printf("%-20s: %p \n", _fnc, __builtin_frame_address(0))


void _my_init(void *mem)
{

}

void *notSafeAlloca(size_t num)
{
    void *mem;
    
    printStackFrameAddr("notSafeAlloca");
    
    mem = alloca(num);
    
    _my_init(mem);
    
    return mem;
}

#define safeAlloca(_num)            \
    ({                              \
        void *ret = alloca(_num);   \
        _my_init(ret);              \
        printStackFrameAddr("safeAlloca");      \
    ret;})

int main(int argc, const char * argv[])
{
    printStackFrameAddr("main");
    
    
    {   /* <- creates no new stack frame ? */
        int *array = notSafeAlloca(sizeof(* array) * 4);
        
        printStackFrameAddr("main");
        
        printf("\t%-20s: %p\n", "array", array);
    }
    
    {   /* <- creates no new stack frame ? */
        int *array = safeAlloca(sizeof(* array) * 4);
        
        printStackFrameAddr("main");
        
        printf("\t%-20s: %p\n", "array", array);
    }
    
    return 0;
}

输出:

main                : 0x7fff5fbff8d0 
notSafeAlloca       : 0x7fff5fbff860 
main                : 0x7fff5fbff8d0 
        array               : 0x7fff5fbff820
safeAlloca          : 0x7fff5fbff8d0 
main                : 0x7fff5fbff8d0 
        array               : 0x7fff5fbff888

alloca() 函数在 堆栈中分配 size 个字节的空间 调用者的框架

那么,以上方法安全吗?

【问题讨论】:

  • 大括号不像堆栈框架In C, do braces act as a stack frame?
  • 您在main() 中的测试尚无定论;很有可能“数组”被优化了,因为它没有被使用。您至少应该打印地址 (printf("%p\n", array);) 看看是否有任何改变。
  • @JonathanLeffler 不,仍然是相同的堆栈帧地址。
  • @d3l:没那么简单。出于复合文字、自动变量等的目的,块的末尾确实结束了此类对象的生命周期。 alloca 相当特殊,因为它创建的对象具有与调用函数相关联的生命周期,而不是与块相关联。要问的问题不是大括号是否“创建堆栈框架”,而是“alloca 创建的对象的生命周期是多少?”

标签: c memory gnu alloca


【解决方案1】:

为我的问题找到了解决方案:)

void *_my_alloca(void *memory)
{
    // init memory & stuff

    return memory;
}

#define my_alloca(_size)   _my_alloca(alloca(_size))

int main(int argc, const char **argv)
{
    int *array = my_alloca(sizeof(* array) * 4);
}

【讨论】:

    【解决方案2】:

    我怀疑你可以,但更重要的是,你为什么要这样做? 这是一个严重的错误!

    你会在堆栈上分配一些东西,让它在你返回它的指令中被销毁!在您有机会使用它之前,它几乎肯定会在堆栈上被覆盖。

    【讨论】:

    • 我知道这一点,我的问题是关于“6.1 表达式中的语句和声明”是否会创建一个新的堆栈框架。如果不是,那就完全没问题了。
    猜你喜欢
    • 2012-02-27
    • 2012-01-28
    • 2016-12-02
    • 1970-01-01
    • 1970-01-01
    • 2011-10-16
    • 2012-01-20
    • 2017-08-28
    • 1970-01-01
    相关资源
    最近更新 更多