tsai@Veritas.COM (Cary Tsai) (06/13/91)
Could you C guru tell me why the third ooprint() stmt causes coredump. I must be missing something in ooprint(). Compile and execute 'a.out'. You'll get 'flag is on', 'flag is off' and ...(coredump) or any bus error message. /* help .... */ #include <stdio.h> #include <varargs.h> typedef void (*PFV)(); void ooprint(va_alist) va_dcl { va_list ap; PFV func; char *client; char *foo; va_start(ap); foo = va_arg(ap, char *); if ((func = va_arg(ap, PFV)) != (PFV) 0) { if ((client = va_arg(ap, char *)) != (char *) 0) func(client); } va_end(ap); } void testFunc1(testData) char *testData; { if (testData && *testData) puts(testData); } void testFunc2(testData) char *testData; { if (testData && *testData) puts(testData); } main() { static char *mess1 = "flag is on"; static char *mess2 = "flag is off"; ooprint("ooprint", testFunc1, mess1); ooprint("ooprint", testFunc2, mess2); ooprint("ooprint"); /* WHY THIS STMT CAUSES CORE-DUMP? */ } /* end of help ... */ You help and information would be appreciated.
willcr@bud.sos.ivy.isc.com (Will Crowder) (06/14/91)
In article <1991Jun12.174326.5390@Veritas.COM>, tsai@Veritas.COM (Cary Tsai) writes: |> Could you C guru tell me why the third ooprint() stmt causes coredump. |> I must be missing something in ooprint(). |> Compile and execute 'a.out'. You'll get 'flag is on', 'flag is off' and |> ...(coredump) or any bus error message. |> |> [most of the source deleted] |> |> va_start(ap); |> foo = va_arg(ap, char *); |> if ((func = va_arg(ap, PFV)) != (PFV) 0) { |> if ((client = va_arg(ap, char *)) != (char *) 0) It looks like you're expecting va_arg to return NULL if there is no argument. This isn't how va_arg() works. REMEMBER: In C, the called function has no idea how many arguments you passed! It generally has no way of knowing, but that's not important. The point is, as far as the language definition is concerned, IT DOESN'T KNOW. You must use either a sentinel value, an explicit argument count, or some other method (such as counting the number of '%' in a printf() format string) to determine how many times you can safely call va_arg() or use the result. I suspect what is happening is you are getting non-NULL garbage data from your ...func = va_arg(ap, PFV)... and then garbage non-NULL data from ...client = va_arg(ap, char *)... and then executing the garbage. If you were to call it as ooprint("ooprint", (PFV) 0); the third time it should work. Hope this helps, Will P.S. (See the FAQ!) -------------------------------------------------------------------------------- Will Crowder, MTS | "That was setting #1. Anyone want to see (willcr@ivy.isc.com) | setting #2?" INTERACTIVE Systems Corp. | -- Guinan
wolfram@messua.informatik.rwth-aachen.de (Wolfram Roesler) (06/14/91)
tsai@Veritas.COM (Cary Tsai) writes: >void ooprint(va_alist) >va_dcl >{ > va_start(ap); > foo = va_arg(ap, char *); > if ((func = va_arg(ap, PFV)) != (PFV) 0) { > if ((client = va_arg(ap, char *)) != (char *) 0) > func(client); ... so you see you always call va_arg at least twice... > ooprint("ooprint"); /* WHY THIS STMT CAUSES CORE-DUMP? */ ... but here you pass only one argument. So the 2nd call to va_arg returns a random value. Since this is likely to be !=0, you call va_arg the 3rd time, which gives you a random value again, and then call what you received in the 2nd call as a function. But, a random value is very unlikely to be a valid function adress... So why should it do anything except a core dump? The problem is that a varargs function can never determine how many args were passed to it. You may pass only one arg and use va_arg to retrieve more than one, but you will get garbage and _not_ null pointers after the arg list is exhausted. BTW: to improve style, use /*VARARGS*/ in front of the function header, this helps using lint on this function. Greetings \/\/olfram
ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (06/15/91)
In article <1991Jun12.174326.5390@Veritas.COM>, tsai@Veritas.COM (Cary Tsai) writes: > Could you C guru tell me why the third ooprint() stmt causes coredump. > I must be missing something in ooprint(). > void ooprint(va_alist) > va_dcl > { > va_list ap; > PFV func; > char *client; > char *foo; > > va_start(ap); > foo = va_arg(ap, char *); > if ((func = va_arg(ap, PFV)) != (PFV) 0) { ^^^^^^ Note: this function ALWAYS tries to access at least two arguments. > ooprint("ooprint", testFunc1, mess1); > ooprint("ooprint", testFunc2, mess2); > ooprint("ooprint"); /* WHY THIS STMT CAUSES CORE-DUMP? */ Why _does_ that statement cause a core dump? Well, WHERE IS THE SECOND ARGUMENT? Failing to supply an argument is not the same as supplying a NULL. I think you mean ooprint("ooprint", (PFV)0); If the function really is as you have presented it, I don't see why you're bothering with varargs at all. It would be simpler just to pass three arguments every time, and to write the 3rd call as ooprint("ooprint", (PFV)0, ""); Better type checking, no worries about varargs -vs- stdargs, &c &c &c. -- Q: What should I know about quicksort? A: That it is *slow*. Q: When should I use it? A: When you have only 256 words of main storage.