Array copy/va_list/pointer prob 
Author Message
 Array copy/va_list/pointer prob

Hi there,

I have the following program (which does not work)

#include <stdarg.h>

void func (int numarg, ...){
  char *cmdp;
  int i;
  va_list ap;

  va_start(ap,numarg);
  for (i =0; i<numarg; i++) {
    *cmdp++= va_arg(ap,char );
  }
  va_end(ap);

Quote:
}

int main(void){
  func(2,"one", "two"); /* number of args and the two args */
  return 0;

Quote:
}

This program segfaults. I think this is because of no space reserved for
the cmdp array (is this an array?) I would like to get an array and
use it for an execv system call (unix), which accepts an array of chars
for the arguments.

Has anybody an idea of how to copy the two parameters into an array so the
execv system call can find its arguments?

--
TIA,

Patrick Gundlach

+--------------------------------------------------+


+--------------------------------------------------+



Sun, 05 Aug 2001 03:00:00 GMT  
 Array copy/va_list/pointer prob
The problem is you are using "*cmdp ++= va_arg (ap, char)"
what 'func (2, "one", "two")' does is, it sets up the arguments:
    arg1 = (int) 2;
    arg2 = (char *)"one"    --> a pointer to an array of chars
    arg3 = (char *)"two"    --> a pointer to an array of chars
and then call func
If you want to get the arguments back from the stack (that's were they are
stored) you could do something like this:

void func2 (int numarg, ...)
{
    int i;
    char **args;
    va_list ap;

    args = (char **)malloc (numarg * sizeof (char *));

    va_start (ap, numargs);
    for (i = 0; i < numarg; i++) {
        args[i] = va_arg (ap, char *)
        printf ("%s\n", args[i]);
    }
    va_end (ap);

Quote:
}

I shall try to explain what I did...

char **args
    this is an pointer to an array of pointers, and each pointer in the
    array points to an array of chars. Uh... I think you have to read this
    more than once....  :)

args = (char **)malloc (numargs * sizeof (char *))
    setup the array. sizeof (char *) gets the amount of bytes needed to
    store an (char *) in memory. This is 2 bytes in tiny, little and compact
    models (I'm not so sure about that) and 4 bytes in medium, large,
    huge and flat (=32 bit, as in Windows programs) memory models.
    Since you need an array with 'numarg' elements, you must allocate
    numarg * sizeof (char *) bytes of memory.
    the (char **) is just there to get a smooth conversion from (void *) to
    (char **).

args[i] = va_arg (ap, char *)
    gets the arguments from stack. each element in in args is of type
    char *. Your arguments can now be accessed from args[0] to
    args[numargs - 1]. If you have an index which is larger than
    (numargs - 1) you'll probably get another segfault

printf ("%s\n", args[i])
    To show you you can acces the arguments now. This prints all
    arguments on the screen, just for debugging purposes.

I hope I helped you out.

Regards,
XtReMe

Patrick Gundlach heeft geschreven in bericht

Quote:
>Hi there,

>I have the following program (which does not work)

>#include <stdarg.h>

>void func (int numarg, ...){
>  char *cmdp;
>  int i;
>  va_list ap;

>  va_start(ap,numarg);
>  for (i =0; i<numarg; i++) {
>    *cmdp++= va_arg(ap,char );
>  }
>  va_end(ap);
>}

>int
n(void){
>  func(2,"one", "two"); /* number of args and the two args */
>  return 0;
>}

>This program segfaults. I think this is because of no space reserved for
>the cmdp array (is this an array?) I would like to get an array and
>use it for an execv system call (unix), which accepts an array of chars
>for the arguments.

>Has anybody an idea of how to copy the two parameters into an array so the
>execv system call can find its arguments?

>--
>TIA,

>Patrick Gundlach

>+--------------------------------------------------+


>+--------------------------------------------------+



Sun, 05 Aug 2001 03:00:00 GMT  
 Array copy/va_list/pointer prob


Quote:
>Hi there,

>I have the following program (which does not work)

>#include <stdarg.h>

>void func (int numarg, ...){
>  char *cmdp;
>  int i;
>  va_list ap;

>  va_start(ap,numarg);
>  for (i =0; i<numarg; i++) {
>    *cmdp++= va_arg(ap,char );

There are a couple of problems here. First you are accessing the value of
cmdp, w2hich is uninitialised. Secondly the 2nd and 2rd arguments being
passed are pointers to char, not just chars.

Quote:
>  }
>  va_end(ap);
>}

>int main(void){
>  func(2,"one", "two"); /* number of args and the two args */
>  return 0;
>}

>This program segfaults. I think this is because of no space reserved for
>the cmdp array (is this an array?)

All you have defined is a pointer. If you want an array of pointers
(and you probably do) you need to write something like

  char *cmdp[MAXARGS+1];

And then you could reference the elemens of it in your loop using cmdp[i]

Quote:
>I would like to get an array and
>use it for an execv system call (unix), which accepts an array of chars
>for the arguments.

You should really express your problems in purely C terms, you
shouldn't assume people here are familiar with exec*() which, as you say,
is a Unix function (although various other systems have similar functions).
You seem to be trying to write a variant of execl() which will probably
do what you want straight off.

Quote:
>Has anybody an idea of how to copy the two parameters into an array so the
>execv system call can find its arguments?

To copy the argument values into an array of character pointers you could

void func (int numarg, ...){
  char **cmdp;
  int i;
  va_list ap;

  if ((cmdp = malloc((numarg+1) * sizeog *cmdp)) == NULL) {
     /* Deal with allocation failure */
  }
  va_start(ap,numarg);
  for (i =0; i<numarg; i++) {
    cmdp[i] = va_arg(ap,char *);
  }
  cmdp[numarg] = NULL;

  free(cmdp);
  va_end(ap);

Quote:
}

--
-----------------------------------------


-----------------------------------------


Sun, 05 Aug 2001 03:00:00 GMT  
 Array copy/va_list/pointer prob
Hi Patrick,

Change func() to:

/* New func() */
char **func (int numarg, ...){
  char **cmdp;                                          
  int i;
  va_list ap;

  cmdp = (char **)malloc(numarg * sizeof(*cmdp));      
  va_start(ap,numarg);
  for (i =0; i<numarg; i++) {
    cmdp[i]= va_arg(ap, char *);
  }
  va_end(ap);

  return cmdp;          /* Don't forget to free this array */

Quote:
}

I hope this to be usefull.

Victor.

Quote:

> Hi there,

> I have the following program (which does not work)

> #include <stdarg.h>

> void func (int numarg, ...){
>   char *cmdp;
>   int i;
>   va_list ap;

>   va_start(ap,numarg);
>   for (i =0; i<numarg; i++) {
>     *cmdp++= va_arg(ap,char );
>   }
>   va_end(ap);
> }

> int main(void){
>   func(2,"one", "two"); /* number of args and the two args */
>   return 0;
> }

> This program segfaults. I think this is because of no space reserved for
> the cmdp array (is this an array?) I would like to get an array and
> use it for an execv system call (unix), which accepts an array of chars
> for the arguments.

> Has anybody an idea of how to copy the two parameters into an array so the
> execv system call can find its arguments?

> --
> TIA,

> Patrick Gundlach

> +--------------------------------------------------+


> +--------------------------------------------------+



Sun, 05 Aug 2001 03:00:00 GMT  
 Array copy/va_list/pointer prob
: Hi there,

: I have the following program (which does not work)

: #include <stdarg.h>

: void func (int numarg, ...){
:   char *cmdp;
:   int i;
:   va_list ap;

:   va_start(ap,numarg);
:   for (i =0; i<numarg; i++) {
:     *cmdp++= va_arg(ap,char );
:   }
:   va_end(ap);
: }

: int main(void){
:   func(2,"one", "two"); /* number of args and the two args */
:   return 0;
: }

: This program segfaults. I think this is because of no space reserved for
: the cmdp array (is this an array?) I would like to get an array and
: use it for an execv system call (unix), which accepts an array of chars
: for the arguments.

: Has anybody an idea of how to copy the two parameters into an array so the
: execv system call can find its arguments?

No, you haven't allocated space for the data read from the argument
strings, and the variable cmdp won't hang around anyway after func()
exits. (You've also got the type of the argument to va_arg() wrong).
The code below will do some of the work, but not all.  You need to
pass cmdp to whatever function needs to use it, and you probably
want to use malloc() to allocate memory rather than a static array.
And error handling needs to be added, and the memory free'd after use.

Will

#include <stdarg.h>
#include <stdlib.h>
#include <string.h>

#define ARGMAX 10

void func(int numarg, ...)
{
  static char *cmdp[ARGMAX];
  char *tmp;
  int i;
  va_list ap;

  if (numarg > ARGMAX) return;

  va_start(ap, numarg);
  for (i = 0; i < numarg; i++) {
        if ((tmp = va_arg(ap, char *)) && (cmdp[i] = malloc(strlen(tmp) + 1)))
                strcpy(cmdp[i], tmp);
        else    
                break;
  }
  va_end(ap);

Quote:
}

int main(void)
{
  func(2, "one", "two"); /* number of args and the two args */
  return 0;
Quote:
}



Sun, 05 Aug 2001 03:00:00 GMT  
 
 [ 7 post ] 

 Relevant Pages 

1. Copy Array string to another Pointer array string in ANSI-C

2. copy of argv to an array (pointers)

3. a va_list in a va_list

4. Array of pointers, pointer to array...

5. Dereferencing f-pointers, arrays of f-pointers, pointers to f-pointers

6. array pointer/pointer array

7. arrays pointers array of pointers

8. Shallow copy or deep copy for System.Array?

9. Copying arrays, copying structs

10. Newbie Prob: Copy to LPT1

11. Use of pointer to va_list

12. Pointer to va_list

 

 
Powered by phpBB® Forum Software