I implemented a function with variable arguments below:
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#define ERR_BUFFER_SIZE 4096
void errPrint(const char *format, ...)
{
va_list argptr;
va_start(argptr, format);
char buf[ERR_BUFFER_SIZE];
vsnprintf(buf, sizeof(buf), format, argptr);
fprintf(stderr, "%s", buf);
va_end(argptr);
}
Then I hope to implement another named "errExit()" based on the function above. I just tried like below.It works as I hoped but I dont't think it correct.
void errExit(const char *format, ...)
{
errPrint(format);
exit(EXIT_FAILURE);
}
I tried errExit("hello,%s,%s,%s", "arg1","arg2", "arg3");
and it printed "hello,arg1,arg2,arg3
" correctly.
But after I added two line code like below, it throwed error Segmentation fault
.
void errExit(const char *format, ...)
{
char buf[4096];//added
strcpy(buf, format);//added
errPrint(format);
exit(EXIT_FAILURE);
}
I am very confused. According to what I learned:
- There is only one argument
format
in the stack of called functionerrPrint()
. I can't believeva_start()
will get arguments from the its parent-functionerrExit()
. - Since
errPrint()
works "correctly", why it doesn't work after I add the two lines code? It seems that the code added have no effect.
(My English is not well, hoping you everyone can stand my statement. Thank you! )
CodePudding user response:
In errExit()
you need to pass the variable arguments to another function via a va_list
argument. As you were not vsnprintf
will eventually crash when trying to access non-existing arguments on the stack.
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ERR_BUFFER_SIZE 4096
void verrPrint(const char *format, va_list ap) {
char buf[ERR_BUFFER_SIZE];
vsnprintf(buf, sizeof(buf), format, ap);
fprintf(stderr, "%s", buf);
}
void errPrint(const char *format, ...) {
va_list ap;
va_start(ap, format);
verrPrint(format, ap);
va_end(ap);
}
void errExit(const char *format, ...) {
va_list ap;
va_start(ap, format);
verrPrint(format, ap);
va_end(ap);
exit(EXIT_FAILURE);
}
int main(void) {
errPrint("What is the meaning of %s\n", "life?");
errExit("%d\n", 42);
return 0;
}
CodePudding user response:
Thank you everyone.I have learned your from your answers. I choose to change my code like below.
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ERR_BUFFER_SIZE 4096
void errPrint(const char *format, va_list arg_list)
{
char buf[ERR_BUFFER_SIZE];
vsnprintf(buf, sizeof(buf), format, arg_list);
fprintf(stderr, "%s", buf);
}
void errExit(const char *format, va_list arg_list)
{
errPrint(format, arg_list);
exit(EXIT_FAILURE);
}
void v_exec(void (*func)(const char *, va_list), const char *format, ...)
{
va_list arg_list;
va_start(arg_list, format);
func(format, arg_list);
va_end(arg_list);
}
int main(void)
{
v_exec(errExit,"%s%d", "hello",520);
return 0;
}