Sign in to follow this  
Craig_jb

Passing va_list to vsprintf

Recommended Posts

After a bit of googling I still can't figure out this one. This code causes a bus error (or segmentation fault on non-mac).
void ErrorLogger::WriteError(std::string p_ErrorFormat, int p_BufferSize, ...)
{

    // format the string
    va_list args;
    char buf[p_BufferSize];
    va_start(args, p_BufferSize);
    std::vsprintf(buf, p_ErrorFormat.c_str(), args);
    va_end(args);

    // print to console
    printf(buf);

    // write to file and push output
    *m_ErrorFile << buf;
    m_ErrorFile->flush();

}

Share this post


Link to post
Share on other sites
The code works for me and I don't see anything wrong with it.
Note however that using a non-const value for a fixed size array is non-standard afaik.
char buf[p_BufferSize];

My testcase

#include <cstdio>
#include <cstdarg>
#include <string>

void WriteError(std::string p_ErrorFormat, int p_BufferSize, ...)
{

// format the string
va_list args;
char buf[p_BufferSize];
va_start(args, p_BufferSize);
std::vsprintf(buf, p_ErrorFormat.c_str(), args);
va_end(args);

// print to console
printf(buf);

// write to file and push output
//*m_ErrorFile &lt;&lt; buf;
// m_ErrorFile-&gt;flush();

}

int main()
{
WriteError("test %s", 256, "works");
}



Share this post


Link to post
Share on other sites
That mix of C and C++ looks rather funky! [smile]

I would not pass the size of the buffer as an argument but simply hard code the size of the buffer. That would change your code to this:

// format the string
char buf[0x400];
memset(buf,0,0x400);

va_list args;
va_start(args, p_ErrorFormat);
std::vsprintf(buf, p_ErrorFormat.c_str(), args);
va_end(args);

Share this post


Link to post
Share on other sites
Much Thank! The only motive I had for passing the length of the buffer as an arguement to the function was to insure the buffer had room for the user's error string. Is there any way to do this safe from segmentation faults?

Share this post


Link to post
Share on other sites
Quote:
Original post by Craig_jb
Much Thank! The only motive I had for passing the length of the buffer as an arguement to the function was to insure the buffer had room for the user's error string. Is there any way to do this safe from segmentation faults?


You could have the user pass in the actual buffer. Or you could do it safe from segmentation faults and type errors, and use standard C++ idioms.


template <typename T>
ErrorLogger& ErrorLogger::operator<<(const T& t) {
std::cerr << t;
(*m_ErrorFile) << t << std::flush;
return *this;
}

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this