Variable length argument list - 32 / 64 bit problem?

J

Joakim Hove

Hello,

I have written the following (stripped down) code:

/********************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>


char * path_fmt_alloc_path(const char * fmt , ...) {
char * new_path;
va_list ap;
va_start(ap , fmt);
{
int path_length = vsnprintf(new_path , 0 , fmt , ap);
new_path = malloc(path_length + 1);
vsnprintf(new_path , path_length + 1 , fmt , ap);
}
va_end(ap);
return new_path;
}


int test(const char * fmt , int id) {
char * s = path_fmt_alloc_path(fmt , id);
printf("%d -> %s \n",id ,s);
free(s);
}



int main(int argc, char **argv) {
const char * fmt = "%d";

test(fmt , 1 );
test(fmt , 2 );
test(fmt , 3 );
}


/*********************************/

When compiling with:
bash% gcc -m32 va_test.c
I get the result:

1 -> 1
2 -> 2
3 -> 3

i.e. what I expected. However it fails when compiling in 64 bit mode:

bash% gcc va_test.c
1 -> -
2 -> 0
3 -> 0

This is done with gcc version 3.4.6...


/***************************/

I am in some invoking undefined behaviour, or is this a bug somewhere
in my 64 bit toolchain?


Best Regards

Joakim Hove
 
D

David Resnick

Hello,

I have written the following (stripped down) code:

/********************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

char * path_fmt_alloc_path(const char * fmt , ...) {
char * new_path;
va_list ap;
va_start(ap , fmt);
{
int path_length = vsnprintf(new_path , 0 , fmt , ap);

new_path is not initialized. You mean to be printing to NULL here to
get the length, but... Maybe whether you get it set to 0/NULL depends
on which compiler you get. I'd suggest (vsnprintf(NULL,...) to make
your meaning clear. If new_path is not 0, you are writing to a wild
pointer.

-David
 
E

Eric Sosman

Joakim said:
Hello,

I have written the following (stripped down) code:

/********************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>


char * path_fmt_alloc_path(const char * fmt , ...) {
char * new_path;
va_list ap;
va_start(ap , fmt);
{
int path_length = vsnprintf(new_path , 0 , fmt , ap);

va_end(ap);
va_start(ap, fmt);
new_path = malloc(path_length + 1);

if (new_path != NULL)
vsnprintf(new_path , path_length + 1 , fmt , ap);
}
va_end(ap);
return new_path;
}


int test(const char * fmt , int id) {
char * s = path_fmt_alloc_path(fmt , id);

if (s != NULL)
printf("%d -> %s \n",id ,s);
free(s);
}



int main(int argc, char **argv) {
const char * fmt = "%d";

test(fmt , 1 );
test(fmt , 2 );
test(fmt , 3 );
}
[...]
I am in some invoking undefined behaviour, or is this a bug somewhere
in my 64 bit toolchain?

Try "refreshing" the va_list and see it that helps.
 
J

Joakim Hove

Hello,

thank you both for answering. I have tried to explicitly initialize
the new_path variable to NULL; but that did unfortunately not help.
     Try "refreshing" the va_list and see it that helps.

Ehhh - what do you mean be refreshing?

Best Regards

Joakim
 
E

Eric Sosman

Joakim said:
Hello,

thank you both for answering. I have tried to explicitly initialize
the new_path variable to NULL; but that did unfortunately not help.


Ehhh - what do you mean be refreshing?

Go back and look at the lines I added to your code.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,754
Messages
2,569,521
Members
44,995
Latest member
PinupduzSap

Latest Threads

Top