【问题标题】:Passing along variadic arguments in C [duplicate]在 C 中传递可变参数
【发布时间】:2023-03-18 16:42:02
【问题描述】:

我正在尝试挂钩一些适用于文件名的 glibc 函数。基本上我需要稍微修改文件名,然后将它与其他参数一起传递给原始 glibc 函数。

代码如下:

FILE *fopen(const char *filename, const char *modes) {
  filename = modify(filename); // assuming we don't need to free the new filename pointer for now
  using FuncT = FILE*(*) (const char *, const char *);
  static FuncT originalFunc = (FuncT)dlsym(RTLD_NEXT, "fopen");
  return originalFunc(filename, modes);
}

这在大多数情况下都可以正常工作,但是当涉及到像 int execl(const char *path, const char *arg, ...) 这样的函数的可变参数时,我该如何正确地做到这一点?

【问题讨论】:

  • 标准库中常见的可变参数函数的版本采用va_list 参数,例如vsnprintf()
  • 在哪里可以找到这些采用 va_list 的函数,例如 execl
  • 查找 va_list 版本是逐个案例。在 execl 的具体情况下,documentation for execl 还提到了 execv 函数,看起来就像你想要的那样。
  • 支持using FuncT = FILE*(*) (const char *, const char *);等记号的C方言不是通常叫C++吗?还是 glibc 的一个特性?
  • 关于FILE *fopen(const char *filename, const char *modes) {filename = modify(filename);,因为参数filename是'指向字符常量的指针,不能修改文件名指向的数据。 这是一个常量,但是可以修改该指针

标签: c


【解决方案1】:

基本上,您不能 - 无法复制您获得的(未解析的)参数列表并将其传递给另一个 varargs 函数。这就是为什么所有 varags 函数都有两种形式的原因——一种采用 ...,另一种采用更具体的参数(显式 va_list 或数组指针)。

execl的情况下,对应的函数是execv——如果你想拦截和“包裹”execl,你的替换函数需要从va_list中提取参数然后调用@987654326 @ 与结果数组。

请注意,库中的所有 execX 函数通常只是编写为调用 execve 的包装器,因此您可能只需要拦截 execve 就可以有效地拦截所有这些函数。

【讨论】:

    【解决方案2】:

    要传递可变数量的参数,您需要知道您期望的参数数量或具有特殊值的参数(如下例所示 - NULL 结束参数列表)。例如,printf 知道格式字符串的预期内容。

    此函数连接字符串。

    #include <stdio.h>
    #include <stdarg.h>
    
    char *concat(char *s1, ...)
    {
        char *saved = s1;
        char *s2;
        va_list ap;
        va_start(ap, s1);
        if(s1)
        {
            while(*s1) s1++;
            while((s2 = va_arg(ap, char *))) while(*s2) *s1++ = *s2++;
        }
        va_end(ap);
        return saved;
    }
    
    int main()
    {
        char s1[64] = "Hello";
        printf("%s\n", concat(s1," World", " !12345!", " QWWERTY ", "@@", NULL));
    
        return 0;
    }
    

    您可以在这里自己玩和试验这个例子:https://onlinegdb.com/HkY5a7pJL

    【讨论】:

    • 所以你建议重新实现对OP想要包装的函数的解析......:/即使这样,如何调用原始函数?
    猜你喜欢
    • 2012-12-29
    • 2011-07-27
    • 1970-01-01
    • 1970-01-01
    • 2021-10-17
    • 2013-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多