AIX上的asprintf的替代或解决方法

bob*_*ood 12 c aix printf asprintf

我正在尝试在AIX上构建python-kerberos.kerberospw.c使用了对asprintf的调用,但是从谷歌告诉我的是,asprintf在AIX上不存在.

我看到http://www.koders.com/c/fidAA9B130D588302673A28B568430A83131B7734C0.aspx?s=windows.h,它看起来像我可以创建一个替身asprintf,但我不知道这个会去或我会怎样#include它在kerberospw.c中.

有没有办法可以使用koders.com示例或其他一些代码"伪造"asprintf?我可以只包含asprintf函数,如kerberospw.c所示?我不是C编码员,但是

asprintf(char**resultp,const char*format,...)

用最后的圆点看起来对我来说不是一个有效的签名.kerberospw.c的相关部分如下

asprintf(消息"%*S:%*S",(int)的result_code_string.length,
(字符*)result_code_string.data,
(INT)result_string.length,
(字符*)result_string.data);

我知道我可以联系上python-的Kerberos的作者,但)我认为这将是有帮助的潜在的补丁,如果我这样做,和b)有可能是其他的软件我碰到运行使用asprintf,这将是很高兴有一个解决方法.

Syl*_*sne 21

asprintfprintf函数族的变体,它分配缓冲区来保存格式化字符串的内存并返回它.它是一个带有可变数量参数的函数(因此...在声明中是有效的C代码).你可以在这里找到描述.

如果vsnprintf功能正常,则可以相对容易地重新实现(即,如果缓冲区太小而无法保存格式化的字符串,则返回错误).

这是一个实现:

#include <stdarg.h>

int asprintf(char **ret, const char *format, ...)
{
    va_list ap;

    *ret = NULL;  /* Ensure value can be passed to free() */

    va_start(ap, format);
    int count = vsnprintf(NULL, 0, format, ap);
    va_end(ap);

    if (count >= 0)
    {
        char* buffer = malloc(count + 1);
        if (buffer == NULL)
            return -1;

        va_start(ap, format);
        count = vsnprintf(buffer, count + 1, format, ap);
        va_end(ap);

        if (count < 0)
        {
            free(buffer);
            return count;
        }
        *ret = buffer;
    }

    return count;
}
Run Code Online (Sandbox Code Playgroud)

  • 此外,`buffer`超出了`*ret = buffer;`行的范围. (2认同)

Jon*_*ler 14

建立在西尔答案,这里是一个简单的实现既asprintf()vasprintf(),因为你需要一个,你通常最终需要其他的了.而且,鉴于va_copy()从C99的宏,很容易实现asprintf()的方面vasprintf().实际上,在编写varargs函数时,将它们成对使用通常很有帮助,一个用省略号表示法,另一个用va_list参数代替省略号,你根据后者简单地实现前者.

这导致代码:

int vasprintf(char **ret, const char *format, va_list args)
{
    va_list copy;
    va_copy(copy, args);

    /* Make sure it is determinate, despite manuals indicating otherwise */
    *ret = NULL;

    int count = vsnprintf(NULL, 0, format, args);
    if (count >= 0)
    {
        char *buffer = malloc(count + 1);
        if (buffer == NULL)
            count = -1;
        else if ((count = vsnprintf(buffer, count + 1, format, copy)) < 0)
            free(buffer);
        else
            *ret = buffer;
    }
    va_end(copy);  // Each va_start() or va_copy() needs a va_end()

    return count;
}

int asprintf(char **ret, const char *format, ...)
{
    va_list args;
    va_start(args, format);
    int count = vasprintf(ret, format, args);
    va_end(args);
    return(count);
}
Run Code Online (Sandbox Code Playgroud)

在未提供这些功能的系统中使用这些功能的棘手部分是决定应该声明功能的位置.理想情况下,他们会在<stdio.h>,但你不需要写它们.所以,你必须有一些其他标题,包括<stdio.h>但如果未声明这些函数,则声明这些函数<stdio.h>.理想情况下,代码应该半自动检测到这一点.也许标题是"missing.h",并包含(部分):

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */

#include <stdio.h>
#include <stdarg.h>

#ifndef HAVE_ASPRINTF
extern int asprintf(char **ret, const char *format, ...);
extern int vasprintf(char **ret, const char *format, va_list args);
#endif /* HAVE_ASPRINTF */
Run Code Online (Sandbox Code Playgroud)

另请注意,asprintf()的此手册页说明指针中的返回值在发生错误时是不确定的.其他手册页(包括问题中引用的手册页)表明它在出错时显式设置为NULL.C标准委员会文件(n1337.pdf)没有规定缺乏内存的错误行为.

  • 如果使用asprintf(),如果函数失败,请不要假设指针已初始化.
  • 如果实现asprintf(),请确保在出错时将指针设置为null以提供确定性行为.