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?
I don't use malloc
because:
argCTemp
and argVTemp
would be fine/remain in scope even if they are on the stack. 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?
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.
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.
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))
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:
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).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.