Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between fprintf and vfprintf in C++? [closed]

I haven't been able to find an answer to the following question, and I am having some issues related to the functions.

My main programming is done in C#, and never really learned C++ while studying, but in my current job I have to do some C++ programming aswell.

Most of the C++ programming have been done by a former employee, and he made a function for logging.

Once in a while this function results in an error (Access Violation) - this is not shown to the user, but I see it while running the code through debugger.

When the error happens it points to this line of code:

vfprintf( LogFile, fmt, va );

I then took a closer look at the code before and after, and to put the above into a context the code around is:

void FileLog( char *fmt, ... )
{
  va_list       va;
  struct  time  t;
  struct  date  d;
  long          clk;
  static int    ReEntrant = 0;

  if( FileLogEnabled == false )
    return;

  ReEntrant++;
  if( ReEntrant > 1 )
    return;

  if( LogFile == NULL )
    LogFile = fopen( LogFileName, "a+" );
  if( LogFile != NULL )
  {
    gettime( &t );
    getdate( &d );
    fprintf( LogFile, "\n%d-%02d-%02d %2d:%02d:%02d.%02d0> ", d.da_year, d.da_mon, d.da_day, t.ti_hour, t.ti_min, t.ti_sec, t.ti_hund );

    va_start( va, fmt );
    vfprintf( LogFile, fmt, va );
    va_end( va );

    fflush( LogFile );
    ...
  }
  ReEntrant = 0;
}

Actually I dont understand why it is needed (and if it is?) call both fprintf and then vfprintf? I would think the first fprintf call would write the formatted string to the stream (File), and that would be enough?

A little explanation or some information would be much appreciated :)

EDIT: After the comment from nos - I tracked down the specific call to the function which today have often been causing this error.

FileLog( "TimerRestore[%d], Name=%s", Package.CurGame->Timers[ Index ].Name.c_str() );

I indeed think this could cause some trouble, as "TimerRestore[%d], Name=%s" should be followed by a decimal and string arguemtn, however only a string argument is given. I need to do some testing, but Im sure the author who wrote this code meant to write:

FileLog( "TimerRestore[%d], Name=%s", Index, Package.CurGame->Timers[ Index ].Name.c_str() );

However I still do not understand why the function call does not always seem to result in an error. Or maybe it is cause of the "ReEntrant" variable in FileLog function is blocking it when it does not fail?

Thanks a lot for all the feedback and information.

like image 339
Knirkegaard Avatar asked Jan 16 '13 12:01

Knirkegaard


People also ask

What is the difference between fprintf and sprintf in C?

fprintf is used to output to stream. sprintf(buffer,...) is used to format a string to a buffer.

What is Vfprintf?

Definition and Usage. The vfprintf() function writes a formatted string to a specified output stream (example: file or database). Unlike fprintf(), the arguments in vfprintf(), are placed in an array.

What is the difference between printf and fprintf function Mcq?

printf function is used to print character stream of data on stdout console. fprintf: fprintf is used to print the string content in file but not on stdout console.


1 Answers

vprintf() (and friends) allow to use va_list as argument, which is useful when your function has a variable amount of arguments:

void log(FILE *file, const char* format, ... )
{
  va_list args;
  va_start (args, format);
  fprintf(file, "%s: ", getTimestamp());
  vfprintf (file, format, args);
  va_end (args);
}

In your application you can call this function with a variable amount of arguments:

log(file, "i=%d\n", i);           // 3 arguments
log(file, "x=%d, y=%d\n", x, y);  // 4 arguments

I do not know why your function results in an error. Your code snippet does not provide enough details. The amount of type of provided function arguments might be the cause.

like image 126
Veger Avatar answered Sep 28 '22 19:09

Veger