2

It's the first time posting so I apologise for any confusion:

I am writing a function like this:

int myFunc(char* inputStr, int *argCTemp, char** argVTemp[]);

The purpose of my function is to take a copy of the input string (basically any user input) and then use strtok to convert it to tokens and populate an array via an array pointer (argV). When myFunc is finished, hopefully I have the argument count and array of strings from my inputStr string.

Here is an example of how I call it:

int main(int argc, char** argv[])
{
    int argCTemp = -1;
    char** argVTemp; 

    // 1 Do Stuff
    // 2 Get input string from user 
    // 3 then call myfunc like this:

    myFunc(inputStr, &argCTemp, &argVTemp);

    // 4: I get garbage whenever I try to use "argVTemp[i]" 
}

My Questions: How should I best do this in a safe and consistent way. How do the pro's do this?


  1. I don't use malloc because:

    • I don't know the number of arguments or the length of each for my input (to dynamically allocate the space). I figured that's why I use pointers
    • since I declare it in the main function, I thought the pointers to/memory used by argCTemp and argVTemp would be fine/remain in scope even if they are on the stack.
  2. I know when myFunc exits it invalidates any stack references it created, so that's why I sent it pointers from a calling function. Should I be using pointers and malloc and such or what?

  3. Last thing: before myfunc exits, I check to see the values of argCTemp and argVTemp and they have valid content. I am setting argCtemp and argVtemp like this:

    (*argCTemp) = argCount;
    (*argVTemp)[0] = "foo";
    

and it seems to be working just fine BEFORE the function exits. Since I'm setting pointers somewhere else in memory, I'm confused why the reference is failing. I tried using malloc INSIDE myFunc when setting the pointers and it is still becoming garbage when myFunc ends and is read by the calling function.

I'm sorry if any of this is confusing and thank you in advance for any help.

2
  • Is this for a learning example. If not there is many a library to parse command line args? Commented Mar 19, 2012 at 5:23
  • This is for a homework assignment. Thanks for the suggestion, unfortunately, I will be parsing input from sockets into an array for use with other functions (the array will be moved around a fair bit to other functions. Thank you though, Any other ideas and such are very welcome :) Commented Mar 19, 2012 at 5:56

3 Answers 3

1

Since "don't know the number of arguments or the length of each for my input ", you can use malloc also. When your buffer abouting full, you should realloc your buffer. The better way: You needn't store whole input. A line, a token or a block is better. Just set a static array to store them. and maybe hash is better if your input more than 100 mb.

I'm sorry for my poor English.

Sign up to request clarification or add additional context in comments.

1 Comment

:D Maybe that with lots of syntax errors. I just hope every one can understand what I really want to say.
0

You send an uninitialized pointer (you call is isn't correct as well, you don't need the & ) to the function, this pointer points to some random place and that is why you get garbage, you can also get segmentation fault.

You can do one of the two.

Per allocate a large enough array which can be static for example

static char * arr[MAX SIZE] and send it (char **)&arr in the function call, or run twice and use malloc.

You should also pass the max size, or use constant and make sure you don't pass it.


Lets say you the number of tokens in int n then

char * arr[] = malloc(sizeof(int *)*n);

this will create array of pointers, now you pass it to your populate function by calling

it with (char **)&arr, and use it like you did in your code

for example (*argVTemp)[0] = ;.

(when the array is not needed any more don't forget to free it by caliing free(arr))

1 Comment

Thank you Roni. I like the idea of running "twice" to figure out the arg count and then malloc an arg array and pass it around. Could you give me an example of how to properly malloc memory, set the pointer and pass that pointer around to other functions (without shooting myself in the foot? I have an idea, but I can't seem to enter code into the response...
0

Generally speaking, since you don't know how many tokens will be in the result you'll need to allocate the array dynamically using malloc(), realloc() and/or some equivalent. Alternatively you can have the caller pass in array along with the array's size and return an error indication if the array isn't large enough (I do this for simple command parsers on embedded systems where dynamic allocation isn't appropriate).

Here's an example that allocates the returned array in small increments:

static
char** myFunc_realloc( char** arr, size_t* elements)
{
    enum {
        allocation_chunk = 16
    };

    *elements += allocation_chunk;
    char** tmp = (char**) realloc( arr, (*elements) * sizeof(char*));

    if (!tmp) {
        abort();  // or whatever error handling
    }

    return tmp;
}

void myFunc_free( char** argv)
{
    free(argv);
}

int myFunc(char* inputStr, int *argCTemp, char** argVTemp[])
{
    size_t argv_elements = 0;
    size_t argv_used = 0;
    char** argv_arr = NULL;


    char* token = strtok( inputStr, " ");

    while (token) {
        if ((argv_used+1) >= argv_elements) {
            // we need to realloc - the +1 is because we want an extra 
            //  element for the NULL sentinel
            argv_arr = myFunc_realloc( argv_arr, &argv_elements);
        }

        argv_arr[argv_used] = token;
        ++argv_used;

        token = strtok( NULL, " ");
    }

    if ((argv_used+1) >= argv_elements) {
        argv_arr = myFunc_realloc( argv_arr, &argv_elements);
    }
    argv_arr[argv_used] = NULL;

    *argCTemp = argv_used;
    *argVTemp = argv_arr;

    return argv_used;
}

Some notes:

  • if an allocation fails, the program is terminated. You may need different error handling.
  • the passed in input string is 'corrupted'. This might not be an appropriate interface for your function (in general, I'd prefer that a function like this not destroy the input data).
  • the user of the function should call myFunc_free() to deallocate the returned array. Currently this is a simple wrapper for free(), but this gives you flexibility to do more sophisticated things (like allocating memory for the tokens so you don't have to destroy the input string).

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.