I wrote the following code :
char arrA[] = "something.";
char arrB[ strlen(arrA) + 5];
And my code behaves vaguely. I am getting the wrong output. First, according to me the problem would be the use of strlen in array declaration. As memory is allocated while compile time and functions are executed at run time. But I didn’t get the error at run time. My code compiled correctly but it is not working as I thought it would be. The best part is I am not using these array anywhere in my code. I am just declaring them.
Why I got no error at compile time ?
Why my code output is unexpected ?
When I comment this second declaration I get the correct output.
I also tried to print the sizeof arrB. Guess what I got 15.
This means it is working correctly. But output is a mess and it should not be working correctly.
What is happening here. Why the thing which I am only declaring, not using anywhere affects my code badily?
My actual code is too big and is different. It would be impossible to explain this error using that code. But I am sharing that code also. This problem in my code is in the function portClearer and for the array completeCommand.
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <regex.h>
int strintToInt(char *str, int len);
void read_command_output(char*, char*, int);
void processIdFinder(char*);
void portClearer(char*);
void compileRegex(regex_t*, char*);
void executeRegex(regex_t*, char*, size_t, regmatch_t*, int);
int main()
{
processIdFinder("dispatcher");
portClearer("4444");
return 0;
}
void read_command_output(char* command, char* buf, int buf_len){
FILE *ps_output_file;
if ((ps_output_file = popen(command,"r"))== NULL){
printf("error\n");
exit(1);
}
if(fgets(buf, buf_len, ps_output_file)==NULL)
printf("%s\n",buf);
fclose(ps_output_file);
return;
}
void compileRegex(regex_t* regexPtr, char* pattern){
if( regcomp(regexPtr, pattern, REG_EXTENDED) ){
fprintf(stderr, "Could not compile regex\n");
exit(1);
}
}
void executeRegex(regex_t* regex, char* buf, size_t nmatch, regmatch_t* reg_matches, int flags){
char errmsgbuf[100];
int err_ret;
err_ret = regexec(regex, buf, nmatch, reg_matches, flags);
if( !err_ret ){
//puts("Match");
return;
}
else if( err_ret == REG_NOMATCH ){
puts("No match");
exit(1);
}
else{
regerror(err_ret, regex, errmsgbuf, sizeof(errmsgbuf));
fprintf(stderr, "Regex match failed: %s\n", errmsgbuf);
exit(1);
}
}
int strintToInt(char *str, int len)
{
int iter, pow_iter, num=0;
for(iter = 0, pow_iter = len-1; iter < len; iter++, pow_iter--)
{
num += (str[iter]-48)* ((int) pow(10,pow_iter));
}
return num;
}
void processIdFinder(char* commandName){
char buf[100], id_proc[10];
regex_t regex;
regmatch_t reg_matches[2];
char command[] = "/bin/ps -C ", commandGrep[] = " | grep ";
char completeCommand[ strlen(command) + strlen(commandGrep) + 2 * 12];
//"/bin/ps -C supervisor | grep supervisor"
strcpy(completeCommand, command);
strcat(completeCommand, commandName);
strcat(completeCommand, commandGrep);
strcat(completeCommand, commandName);
read_command_output(completeCommand, buf, 100);
compileRegex(®ex, "^ *([1-9]+) ?");
executeRegex(®ex, buf, (size_t) 2, reg_matches, 0);
//fetching result
//printf("%d and %d ----- %c and %c\n",reg_matches[1].rm_so,reg_matches[1].rm_eo,buf[reg_matches[1].rm_so],buf[reg_matches[1].rm_eo - 1]);
strncpy(id_proc,buf+reg_matches[1].rm_so, reg_matches[1].rm_eo - reg_matches[1].rm_so);
printf("(%s)\n",id_proc);
printf("%d\n",strintToInt(id_proc,strlen(id_proc))); //its important to write strlen here not 10
return;
}
void portClearer( char* portNo){
char buf[100], id_proc[10];
regex_t regex;
regmatch_t reg_matches[2];
char command[] = "/bin/netstat -nlp | grep ";
char completeCommand[ strlen(command) + 5 ];
//char completeCommand[ 25 + 5 ];
printf("%d\n", sizeof(completeCommand));
//strcpy(completeCommand, command);
//strcat(completeCommand, portNo);
read_command_output("/bin/netstat -nlp | grep 4444", buf, 100);
compileRegex(®ex, "[1-9]+/");
executeRegex(®ex, buf, (size_t) 1, reg_matches, 0);
//fetching result
//printf("%d and %d ----- %c and %c\n",matches[0].rm_so,matches[0].rm_eo,buf[matches[0].rm_so],buf[matches[0].rm_eo - 1]);
strncpy(id_proc,buf+reg_matches[0].rm_so, reg_matches[0].rm_eo - reg_matches[0].rm_so-1);
printf("(%s)\n",id_proc);
printf("%d\n",strintToInt(id_proc,strlen(id_proc))); //its important to write strlen here not 10
return;
}
This is a variable length array (which were introduced in C99):
which explains why it compiles if your compiler has C99 support enabled.
This is incorrect:
as it is using
bufin the event thatfgets()fails (and is the probable cause of the output being a mess). It should be:Note that
strncpy()does not append a null terminator, but may copy it from the source buffer to the destination buffer. This means it is not guaranteed thatid_procwill be null terminated. Ifid_procis not null terminated and passed toprintf("%s")garbage will most likely appear after the content ofid_proc.