在 GCC 中动态创建 va_list - 可以做到吗?

2023-11-22

我的问题是vsprintf是我无法直接获取输入参数,我必须先逐一获取输入并将它们保存在void**,然后通过这个void** to vsprintf(),对于windows来说一切都很好,但是当我来到64位linux时,gcc无法编译,因为它不允许从void** to va_list,有谁可以给​​我一些帮助,我应该如何在linux下做到这一点?

我可以在 GCC 中动态创建 va_list 吗?

void getInputArgs(char* str, char* format, ...)
{
    va_list args;
    va_start(args, format);
    vsprintf(str, format, args);
    va_end(args);
}  

void process(void)
{
    char s[256];
    double tempValue;
    char * tempString = NULL;
    void ** args_ptr = NULL;
    ArgFormatType format;   //defined in the lib I used in the code
    int numOfArgs = GetNumInputArgs();  // library func used in my code

    if(numOfArgs>1)
    {
        args_ptr = (void**) malloc(sizeof(char)*(numOfArgs-1));
        for(i=2; i<numOfArgs; i++)
        {
            format = GetArgType();    //library funcs

            switch(format)
            {
                case ArgType_double:
                    CopyInDoubleArg(i, TRUE, &tempValue);   //lib func
                    args_ptr[i-2] = (void*) (int)tempValue;    
                    break;

                case ArgType_char:
                    args_ptr[i-2]=NULL;
                    AllocInCharArg(i, TRUE, &tempString);  //lib func
                    args_ptr[i-2]= tempString;
                break;
            }
        }
    }

    getInputArgs(s, formatString, (va_list) args_ptr);   //Here 
           // is the location where gcc cannot compile, 
           // Can I and how if I can create a va_list myself?
}

有一种方法可以做到这一点,但它是specific to gcc在 Linux 上。它确实可以在 Linux 上运行(已测试),适用于 32 位和 64 位版本。

免责声明:我不认可使用此代码。它不便于携带,而且很简陋,而且坦率地说,它是众所周知的走钢丝的一头不稳定的平衡大象。我只是证明可以动态创建一个va_list using gcc,这就是最初的问题所问的。

话虽如此,下面的文章详细介绍了如何va_list与 amd64 ABI 配合使用:Amd64 和 Va_arg.

了解了内部结构va_liststruct,我们可以欺骗va_arg宏从 a 读取va_list我们自己构建:

#if (defined( __linux__) && defined(__x86_64__))
// AMD64 byte-aligns elements to 8 bytes
#define VLIST_CHUNK_SIZE 8
#else
#define VLIST_CHUNK_SIZE 4
#define _va_list_ptr _va_list
#endif

typedef struct  {
    va_list _va_list;
#if (defined( __linux__) && defined(__x86_64__))
    void* _va_list_ptr;
#endif
} my_va_list;

void my_va_start(my_va_list* args, void* arg_list)
{
#if (defined(__linux__) && defined(__x86_64__))
    /* va_args will read from the overflow area if the gp_offset
       is greater than or equal to 48 (6 gp registers * 8 bytes/register)
       and the fp_offset is greater than or equal to 304 (gp_offset +
       16 fp registers * 16 bytes/register) */
    args->_va_list[0].gp_offset = 48;
    args->_va_list[0].fp_offset = 304;
    args->_va_list[0].reg_save_area = NULL;
    args->_va_list[0].overflow_arg_area = arg_list;
#endif
    args->_va_list_ptr = arg_list;
}

void my_va_end(my_va_list* args)
{
    free(args->_va_list_ptr);
}

typedef struct {
    ArgFormatType type; // OP defined this enum for format
    union {
        int i;
        // OTHER TYPES HERE
        void* p;
    } data;
} va_data;

现在,我们可以生成va_list指针(对于 64 位和 32 位版本都是相同的)使用类似你的process()方法或如下:

void* create_arg_pointer(va_data* arguments, unsigned int num_args) {
    int i, arg_list_size = 0;
    void* arg_list = NULL;

    for (i=0; i < num_args; ++i)
    {
        unsigned int native_data_size, padded_size;
        void *native_data, *vdata;

        switch(arguments[i].type)
        {
            case ArgType_int:
                native_data = &(arguments[i].data.i);
                native_data_size = sizeof(arguments[i]->data.i);
                break;
            // OTHER TYPES HERE
            case ArgType_string:
                native_data = &(arguments[i].data.p);
                native_data_size = sizeof(arguments[i]->data.p);
                break;
            default:
                // error handling
                continue;
        }

        // if needed, pad the size we will use for the argument in the va_list
        for (padded_size = native_data_size; 0 != padded_size % VLIST_CHUNK_SIZE; padded_size++);

        // reallocate more memory for the additional argument
        arg_list = (char*)realloc(arg_list, arg_list_size + padded_size);

        // save a pointer to the beginning of the free space for this argument
        vdata = &(((char *)(arg_list))[arg_list_size]);

        // increment the amount of allocated space (to provide the correct offset and size for next time)
        arg_list_size += padded_size;

        // set full padded length to 0 and copy the actual data into the location
        memset(vdata, 0, padded_size);
        memcpy(vdata, native_data, native_data_size);
    }

    return arg_list;
}

最后,我们可以使用它:

va_data data_args[2];
data_args[0].type = ArgType_int;
data_args[0].data.i = 42;

data_args[1].type = ArgType_string;
data_args[1].data.p = "hello world";

my_va_list args;
my_va_start(&args, create_arg_pointer(data_args, 2));

vprintf("format string %d %s", args._va_list);

my_va_end(&args);

现在你就得到了它。有用mostly和正常一样va_start and va_end宏,但允许您传递自己动态生成的字节对齐指针以供使用,而不是依赖调用约定来设置堆栈帧。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 GCC 中动态创建 va_list - 可以做到吗? 的相关文章

  • 为什么我应该使用内联代码? [复制]

    这个问题在这里已经有答案了 我是一名 C C 开发人员 这里有几个始终困扰我的问题 常规 代码和内联代码之间有很大区别吗 主要区别是什么 内联代码只是宏的一种 形式 吗 选择内联代码时必须进行什么样的权衡 Thanks 表现 正如之前的答案
  • 为什么使用数组索引循环数组比指针访问慢?

    我正在读Kochan的书 Programming in C 在第 14 页的 指针和数组 部分中 264 他说 一般来说 索引数组的过程比执行索引过程花费更多的时间 访问指针内容的过程 其实这也是主要原因之一 为什么使用指针来访问数组的元素
  • OpenCV SVM 给出奇怪的预测结果

    我对 OpenCV 和支持向量机都很陌生 我想使用 SVM 训练具有两个标签的数据集 然后预测给定集合的标签 我当前的集合包含大约 600 行 具有相等的类分布 1 为 300 行 1 为 300 行 包含 34 列 这是我当前用于设置 O
  • 如何用另一个静态变量初始化一个静态变量?

    静态1 hpp include
  • 提取单花括号内的值

    我想要一个收藏 value 一个字符串使用正则表达式 例如 lorem ipsum field1 lorem ipsum field2 lorem ipsum field1 lorem ipsum field2 field3 我会得到 fi
  • 带有嵌入 Flash 视频的 PDF 示例?

    有谁知道我在哪里可以查看嵌入 Flash 视频的 PDF 示例 我知道问这个问题很愚蠢 因为你会认为任何面向技术的用户都应该能够使用谷歌找到一个 但我真的找不到 我的另一个问题是 使用 C 中的 API 将 Flash 视频嵌入 PDF 文
  • 我如何知道向量的实际最大大小? (不使用 std::vector::max_size)

    在在线课程中 我正在学习向量 在其中一个例子中 他们解释说 std vector max size 应该给我向量可以达到的最大大小 我决定测试一下 include
  • Web浏览器控件:如何捕获文档事件?

    我正在使用 WPF 的 WebBrowser 控件加载一个简单的网页 在这个页面上我有一个锚点或一个按钮 我想在我的应用程序后面的代码中 即在 C 中 捕获该按钮的单击事件 WebBrowser 控件是否有办法捕获加载页面元素上的单击事件
  • 在 Linq 查询中使用动态列名称

    foreach Dimension dimensions in Enum GetValues typeof Dimension var r new ReferenceTable dimensions referenceItems List
  • 使用左连接获得不适当的输出

    我正在尝试获取变体列表 并且对于每个变体都获取所有subvariants list无论子变体属于何处 特别的Test say 100 这是示例数据 Id TestId SourceSubVariantId TargetSubVariantI
  • 使用信号和槽更新指针

    我对 Qt 很陌生 请帮我解决这个问题 我正在使用线程在后台执行密集操作 同时我想更新 UI 所以我使用 SIGNALS 和 SLOTS 为了更新 UI 我发出一个信号并更新 UI 让我们考虑下面的示例代码 struct sample QS
  • C++ 模板参数数量错误(2,应该是 1)

    我使用 C 并行快速排序程序进行了测试 如下所示 首先使用列表作为容器 然后我转移到通用容器类型 但它报告了标题错误 可以帮忙解决这个问题吗 include
  • 从 AuthorizeAttribute 继承的属性不起作用

    我目前正在尝试根据用户角色在新的 ASP MVC 5 应用程序中实现安全性 目标是防止用户在没有特定角色 或更高角色 的情况下访问某些控制器或控制器方法 根据到目前为止我所读到的问题 我创建了一个继承 AuthorizeAttribute
  • 如何解决 boost::multi precision::cpp_dec_float 除法错误

    除以boost multiprecision cpp dec float有某种舍入误差 如下 include
  • 在链表程序中使用模板时重载 C++ 中的 << 运算符

    我正在尝试实现一个链接列表 但是当我尝试重载 include
  • C++ 在预处理器 #if 中对 sizeof() 比较抛出编译错误

    我有这个 它不会从 Visual Studio 编译错误 致命错误 C1017 无效的整数常量表达式 我该怎么做 template
  • 如何使用 .NET 捕获我的桌面视频?

    我想知道是否有任何方法可以使用 NET 捕获我的桌面的视频 截屏视频 我并不是在寻找截屏软件 而只是在寻找一种可以让我自己生成桌面视频的技术 我想过拍摄多个屏幕截图 但我不确定如何以编程方式生成带有图像序列的视频 有人有主意吗 Thanks
  • 调用泛型类的方法

    这是上下文 我尝试编写一个映射器来动态地将域模型对象转换为 ViewModel 对象 我遇到的问题是 当我尝试通过反射调用泛型类的方法时 出现此错误 System InvalidOperationException 无法对 Contains
  • 小数精度

    我使用小数类型进行高精度计算 货币 但我今天遇到了这个简单的划分 1 1 37 这应该再次得到 37 http www wolframalpha com input i 1 2F 281 2F37 29 http www wolframal
  • 推断“x => { throw .. }”的 Lambda 与重载方法中的 Func 匹配吗?

    我不明白为什么 C 最终在以下 LINQPad 代码中执行不正确的扩展方法 void Main Actual Sync Action Expected Sync Action Run x gt x Dump Actual Async Tas

随机推荐

  • 不使用互操作/非托管代码监控打印后台打印

    背景 我正在使用 NET 4 0 用 C 编写一个应用程序 它按一定顺序打印一堆文档 这些文档具有不同的类型 并且实际上是使用 ShellExecute 和 print 动词打印的 为了确保顺序不会混乱 我想检查相关打印机的打印队列 我的主
  • 使用 javascript 设置 maxlength

    我正在尝试使用 JavaScript 动态设置输入字段的最大长度 显然这是 IE 的问题 我找到了部分解决方案 input title get 0 setAttribute max length 25 input title get 0 s
  • 查找 .NET 解决方案中未使用的资源

    如何在 resx 文件中查找可能已成为 孤立 且不再需要的未使用的图标 图像 字符串 最近ResXManager 1 0 0 41添加了一项功能来显示对字符串资源的引用数量
  • LINQ、Where() 与 FindAll()

    有人可以解释 LINQ 函数Where 和FindAll 有何不同吗 他们俩似乎都在做同样的事情 FindAll 是一个函数List
  • htons 中的混乱 - 小端/大端

    当我通过套接字从一个进程向另一个进程发送一个整型变量 然后在接收端打印该值时 在不使用ntohl htonl的情况下该值仍然相同 那么除了初始化套接字结构之外 我还需要在哪里使用这些函数 我理解小 大端 但是 当值保持不变时 为什么我们需要
  • 使用前向和后向正则表达式时出错

    我在使用以下正则表达式时遇到问题 它在 regexr 和 rubular 中运行良好 但在 node js 上运行时出现错误 我对使用正则表达式相当陌生 我不确定我做错了什么 如果我关掉它就会起作用 lt 所以我认为这就是问题所在 我正在尝
  • 照亮\广播\广播异常 无消息

    我在用着由 beyondcode 编写的 Laravel websocket 几天后 我已经连接到myDomain com laravel websockets第一步解决了 但现在 当我触发event laravel此时出现错误 publi
  • 如何前瞻性地使用Pandas的rolling_*函数

    假设我有一个时间序列 In 138 rng pd date range 1 10 2011 periods 10 freq D In 139 ts pd Series randn len rng index rng In 140 Out 1
  • 清除情节提要中使用的标签文本

    想知道是否有人知道如何完成以下 In a Storyboard我用虚拟文本设置标签 它们不是静态文本 例如 User1 用户名 我想知道是否有一个设置可以在视图加载该标签时清除该标签的值 我还有一些其他代码可以运行并收集相关信息 但是 可能
  • 检查 TypeScript 中的枚举中是否存在值

    我收到一个号码type 3并且必须检查它是否存在于该枚举中 export const MESSAGE TYPE INFO 1 SUCCESS 2 WARNING 3 ERROR 4 我发现的最好方法是将所有枚举值作为数组获取并在其上使用in
  • 函数式编程——for 和 while 循环

    我正在尝试写for and whilePython 中的循环 函数式编程风格 I think for构造很好 但是while不起作用 它无限运行 for loop lst 1 2 3 def fun e return e print map
  • 为什么 Seq.iter 和 Seq.map 慢这么多?

    考虑 F 中的以下代码 let n 10000000 let arr Array init n fun gt 0 let rec buildList n acc i if i n then acc else buildList n 0 ac
  • GAWK:strftime() 的逆 - 使用格式模式将日期字符串转换为自纪元时间戳以来的秒数

    Gnu AWK 提供内置函数 strftime 它可以转换时间戳1359210984 into Sat 26 Jan 15 36 24 CET 2013 我找不到可以执行此操作的函数 seconds timefromdate Sat 26
  • 如何在 iOS 9.0 Beta 中实现新的 Core Data 模型构建器“唯一”属性

    在 WWDC15 视频会议中 核心数据的新变化 在 10 45 分钟 演示开始时 Apple 工程师描述了模型构建器的一项新功能 该功能允许您指定独特的属性 一旦设置了这些唯一属性 Core Data 将不会创建具有该属性的重复对象 这是为
  • 根据两列分配唯一ID [重复]

    这个问题在这里已经有答案了 我有一个数据框 df 如下所示 School Student Year A 10 1999 A 10 2000 A 20 1999 A 20 2000 A 20 2001 B 10 1999 B 10 2000
  • MediaPlayer 在 Android 4.4 上随机停止 (19)

    我的应用程序在除 Nexus 5 之外的所有设备上都可以正常传输音频 在 Nexus 5 上 MediaPlayer 随机停止播放 不确定响度是否发生变化 http developer android com about versions
  • Boost Spirit可以用来解析字节流数据吗?

    Spirit Boost C 库的一部分 可以用来解析来自流的二进制数据吗 例如 它可以用来将来自套接字的数据解析为结构 字节和单独的位标志吗 谢谢 Boost Spirit 允许使用定义解析器扩展巴科斯 诺尔范式 EBNF 语法与模板元编
  • DataFrame 到列表的列表,不更改值的数据类型

    df values to list or list df values 将数据帧转换为列表列表 但整数值转换为浮点值 数据框是 HSCode value year 0 2 0 18 2018 1 3 0 00 2018 2 4 12 48
  • Django:查询使用包含列表中的每个值

    我需要执行 django 查询来检查字段是否包含列表中的所有值 该列表的长度会有所不同 Example User objects filter first name contains x y z import operator from d
  • 在 GCC 中动态创建 va_list - 可以做到吗?

    我的问题是vsprintf是我无法直接获取输入参数 我必须先逐一获取输入并将它们保存在void 然后通过这个void to vsprintf 对于windows来说一切都很好 但是当我来到64位linux时 gcc无法编译 因为它不允许从v