Re: Segmentation fault in vsnprintf() from /lib64/tls/libc.so.6



In article <1165255972.273510.167660@xxxxxxxxxxxxxxxxxxxxxxxxxxx>
saumya.agarwal@xxxxxxxxx <saumya.agarwal@xxxxxxxxx> wrote:
On executing the code (snippet below) I get a segmentation fault at run
time. ... The crash happens in the second iteration of the for loop.

if (NULL != *strp) {
for ( ; NULL != *strp; ) {
left = *sizep - len - 1;
if (left > 0) {
result = vsnprintf(&(*strp)[len], left, format, ap);
if ((result != -1) && (result < left)) { //vsnprintf
truncated the output string
break;
}
}
*sizep *= 2;
Renew(*strp, *sizep, char); //reallocate sizep amount of
space to strp
}
}

(I think it is worth pointing out that this code snippet will no
longer compile due to line-wrapping of "//" comments. C89-style
comments survive USENET posting better than these C99-specific
comments.)

You have already gotten a correct answer from insik.park@xxxxxxxxx
(namely, the v*printf family of functions destroy the "ap" parameter,
at least in theory, and sometimes but not always in practice).

The snippet above does not have enough information to tell whether
this can be fixed without using a new C99 feature. If your function
looks something vaguely like:

void foo(const char *fmt, ...) {
va_list ap;

va_start(ap, fmt);
some_sort_of_loop {
/* BUG HERE - may fail if the loop runs more than once */
result = some_vprintf_function(args, ap);
...
}
va_end(ap);
}

you can rewrite it as:

void foo(const char *fmt, ...) {
va_list ap;

some_sort_of_loop {
va_start(ap, fmt);
result = some_vprintf_function(args, ap);
va_end(ap);
...
}
}

But in general it is better to write a function like foo() in
terms of its "vfoo" counterpart:

void foo(const char *fmt, ...) {
va_list ap;

va_start(fmt, ap);
vfoo(fmt, ap);
va_end(ap);
}

void vfoo(const char *fmt, va_list ap) {

some_sort_of_loop {
/* BUG HERE */
result = some_vprintf_function(args, ap);
...
}
}

In this case, there is no way to "va_end" and "re-va_start" inside
the loop. C99 provides the missing part of the puzzle, using a
macro[%] spelled "va_copy":

void vfoo(const char *fmt, va_list ap) {
va_list copy;

some_sort_of_loop {
va_copy(ap, copy);
result = some_vprintf_function(args, copy);
va_end(copy);
...
}
}

Instead of re-"va_start"-ing, you va_copy the still-valid "ap"
value, then va_end the copy, inside the loop.
-----
[% At least, the C99 draft I have specifies "a macro". If it is
required to be a macro, you can test for its presence, even in a
compiler that is not yet fully C99-conformant, with "#ifdef".]
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
.



Relevant Pages