Unable to dynamically create an array of params for execv in C
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Unable to dynamically create an array of params for execv in C
Hello everyone and thank you for looking at my little problem. I haven't programmed in C for a while, so I am trying to remember certain aspects of syntax. I have a program that will fork and exec other programs. Those programs will be specified on the command line as follows:
./main "prog1 arg arg ..." "prog2 arg arg ..."
Here is the main snippet:
int countChar(char* s, char c)
{
int cnt = 0;
int len = strlen(s);
for(int i = 0; i < len; i++)
{
The highlighted line is the problem. I get this error:
dualstarter.cpp:58: error: initializer fails to determine size of ‘params’.
Right now I am thinking of creating an array with the specified size and simply copying the required string into it, but it just seems like there is an easier way. I appreciate any feedback you have, thank you.
The highlighted line is the problem. I get this error:
dualstarter.cpp:58: error: initializer fails to determine size of ‘params’.
Right now I am thinking of creating an array with the specified size and simply copying the required string into it, but it just seems like there is an easier way. I appreciate any feedback you have, thank you.
I guess it feels great to wave the C99 standard in my face and imply: "You are stupid, didn't you read this whole document to not make such stupid mistakes?" If that was not your intent, I apologize, but it very much comes off like that. Nonetheless, having searched through the document the closest thing I could find was on page 117:
EXAMPLE 3 The following declarations demonstrate the compatibility rules for variably modified types.
extern int n;
extern int m;
void fcompat(void)
{
int a[n][6][m];
int (*p)[4][n+1];
int c[n][n][6][m];
int (*r)[n][n][n+1];
p = a; // invalid: not compatible because 4 != 6
r = c; // compatible, but defined behavior only if
// n == 6 and m == n+1
}
Except in my case I was trying to shift the pointer from the existing array by one value down and declare a new array starting from the shifted value:
int a[3];
int b[2] = &a[1];
As I already know this does not work, but my question is - is there a way for me to do what I want?
I guess it feels great to wave the C99 standard in my face and imply: "You are stupid, didn't you read this whole document to not make such stupid mistakes?" If that was not your intent, I apologize, but it very much comes off like that. Nonetheless, having searched through the document the closest thing I could find was on page 117:
EXAMPLE 3 The following declarations demonstrate the compatibility rules for variably modified types.
extern int n;
extern int m;
void fcompat(void)
{
int a[n][6][m];
int (*p)[4][n+1];
int c[n][n][6][m];
int (*r)[n][n][n+1];
p = a; // invalid: not compatible because 4 != 6
r = c; // compatible, but defined behavior only if
// n == 6 and m == n+1
}
Except in my case I was trying to shift the pointer from the existing array by one value down and declare a new array starting from the shifted value:
int a[3];
int b[2] = &a[1];
As I already know this does not work, but my question is - is there a way for me to do what I want?
What does the standard say about initialization ? The example you posted is not related to initialization, your problem is.
Page 127:
22. If an array of unknown size is initialized, its size is determined by the largest indexed
element with an explicit initializer. At the end of its initializer list, the array no longer
has incomplete type.
I guess for the compiler to initialize the array it needs to be defined with an explicit brace notation... Hmm, I'll have to figure out how to initialize through the brace notation I guess.
Page 127:
22. If an array of unknown size is initialized, its size is determined by the largest indexed
element with an explicit initializer. At the end of its initializer list, the array no longer
has incomplete type.
I guess for the compiler to initialize the array it needs to be defined with an explicit brace notation... Hmm, I'll have to figure out how to initialize through the brace notation I guess.
So now it's high time to talk about stupidity.
Quote:
You are stupid, didn't you read this whole document
- yes, to write such a thing is stupid. Specifically, it is stupid because:
the compiler tells something about initialization;
the above item in bold is common for words like "initial", "initializer", "initialization", etc;
the standard is a PDF file, hence electronic search does work;
the item (substring) to be looked for is, of course, "initial";
in the light of all the above it is utterly stupid to assume the whole document should be read.
I get what you are trying to do. "Don't give the fish to the man, but teach him to fish." I did search through the document, and I did find the section about initialization. The part about "whole document" was an exaggeration. My problem is that the size of the array can not be determined by the compiler during the initialization. The closest thing I could find I already posted. Just FYI, searching for "initial" brings up 368 references, if the document didn't contain the contents section plowing through that would be a little too much. Also, just some constructive criticism:
In my understanding the point of the website is to help people with Linux problems, in my case a programming problem in Linux environment. I do not expect you to solve my problem and give me the solution on the silver platter. Simply explain what I am doing wrong in a snippet of the code that does not work, and maybe tell me how I can fix it. Your approach is to show me the language standard, which is equivalent to showing the construction worker a blueprint of the tool he is having trouble with and tell him the answer is there. Of course the answer is SOMEWHERE there, but thats the reason this website exists - to find people who already know the part of the blueprint you are looking for and explain it to you, so you don't have to read the unnecessary information. A funny thing, you still didn't say if I am on the wrong or the right track and I get the gist you don't know yourself. You saw the post, didn't know the answer, but your ego simply couldn't resist, so you sent me on the search adventure. In your last post you come off as a douchbebag, but please pay attention to the words, you COME OFF as one, not that I am calling you that.
This way you do not need to parse any strings, just split the argv[] into multiple arrays at "---" strings (allowing for a trailing "---"); no string operations needed except for strcmp(), just pointer array stuff. The shell will then handle the argument parsing/splitting, handling quotes and all that mess.
Since this works exactly like other programs with respect to argument parsing, there would be no surprises for users. Consider, for example, how in your calling convention you would handle spaces in parameters.
You'll find the code is much, much simpler this way, too.
If you really need your calling convention for some reason, you could then use a simple wrapper script:
Code:
#!/bin/bash
ARGS=()
while [ $# -gt 0 ]; do
ARGS=("${ARGS[@]}" $1 ---)
shift 1
done
exec path-to-real-main "${ARGS[@]}"
This would always use Bash parameter splitting rules, thus minimal surprise for users.
Nominal Animal
Last edited by Nominal Animal; 03-21-2011 at 01:45 AM.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.