C 为什么两次调用vprintf或类似函数都不起作用,甚至出现故障?
我的程序中出现了一个分段错误,并且能够在这个简单的示例中可靠地重现它:C 为什么两次调用vprintf或类似函数都不起作用,甚至出现故障?,c,linux,segmentation-fault,variadic-functions,C,Linux,Segmentation Fault,Variadic Functions,我的程序中出现了一个分段错误,并且能够在这个简单的示例中可靠地重现它: #include <stdio.h> #include <syslog.h> #include <stdarg.h> // if I remove at least one of the args, segfault does not happen void doLog(unsigned int arg0, unsigned int arg1, unsigned int arg2, co
#include <stdio.h>
#include <syslog.h>
#include <stdarg.h>
// if I remove at least one of the args, segfault does not happen
void doLog(unsigned int arg0, unsigned int arg1, unsigned int arg2, const char* format, ...)
{
va_list args;
va_start(args, format);
// by default - to both console and syslog
vprintf(format, args);
// next v* function call causes segfault, no matter if vprintf or vsyslog
//vprintf(format, args);
vsyslog(LOG_WARNING, format, args);
va_end(args);
}
int main(int argc, char *argv[])
{
// if I remove at least one of the function args or an %s in the string, the segfault does not happen
doLog(1, 2, 3, "Format with args %s , %s", "1", "2");
return 0;
}
#包括
#包括
#包括
//如果删除至少一个参数,则不会发生SEGFULT
void doLog(无符号整数arg0、无符号整数arg1、无符号整数arg2、常量字符*格式,…)
{
va_列表参数;
va_开始(参数,格式);
//默认情况下-控制台和系统日志
vprintf(格式,参数);
//下一个v*函数调用会导致segfault,无论是vprintf还是vsyslog
//vprintf(格式,参数);
vsyslog(日志警告、格式、参数);
va_端(args);
}
int main(int argc,char*argv[])
{
//如果删除字符串中的至少一个函数args或%s,则不会发生SEGFULT
doLog(1,2,3,“使用参数%s,%s的格式”,“1”,“2”);
返回0;
}
这是怎么回事?为什么对vprintf或vsyslog的第二次调用会导致segfault,为什么它只会发生在特定数量的函数参数上?即使我删除了一些参数以避免segfault,第二次输出仍然是错误的
有关我的环境的一些信息:
- OS:(
)Linux lexdeb 3.16.0-4-amd64#1 SMP Debian 3.16.7-ckt25-2+deb8u3(2016-07-02)x86_64 GNU/Linux(lexdeb只是主机名)uname-a
- gcc版本4.9.2(Debian 4.9.2-10)
- 该程序位于main.c文件中
vprintf
手册页:
int vprintf(const char *format, va_list ap);
(…)因为调用了va_arg
宏,调用后ap
的值未定义。请参见标准(3)
所以当你到达:
vsyslog(LOG_WARNING, format, args);
args
未定义,导致行为未定义。您可能需要阅读va_copy
的手册页。您应该始终使用gcc-Wall
进行编译,并且经常使用-g
@EOF进行编译。谢谢,这很有意义。这是否意味着v*函数本身不调用va_copy以确保安全处理args?@JustAMartin如果不多次使用va_列表
,复制它是浪费时间。如果v*printf()
-家族复制了va_list
参数,您无法避免这种时间浪费。但它也表示他们不调用va_end
,调用者需要调用va_end
。