Segmentation fault when trying to check command line arguments (in C) - c

I wanted to give several arguments in the command line, like:
./programName -a 103 -p argument1,argument2,argument3
Then, I wanted to create several variables with values of these arguments: one integer variable for the number just after the flag -a, one integer variable for the number of arguments just after the flag -p and one array variable with all these arguments.
It would be always the same arguments (so my code can not manage other forms of input): -a (integer) -p (a list of arguments separated with ,)
My problem is that there is a segmentation fault. After several attempts to see where it occurs (using several printf), there is a segmentation fault when the variable a = 3 (so at the flag -p). And the segmentation occurs at the line "case 'p'".
I don't understand why this code accepts the argument "-a" but not "-p". And I don't think there is an error because of my code in the "case 'p'" because the segmentation fault occurs after that (on the line "case 'p'").
I hope you'll understand my problem and thank you for your help :).
EDIT:
Thanks to Mark Wilkins and ooga for their answers. The segmentation fault was indeed due to the individual elements of the array which wasn't initialized.
If some people don't know how to efficiently initialize an array of strings, check this other question, it's well explained ;) :
Initialize array of strings

One issue that would result in a segmentation fault is the use of arg_p. It is declared as an array of char*, but the individual elements of the array are never initialized. The subsequent use of it will result in accessing an uninitialized pointer:
*(arg_p[b]+c) = *(chrp+c);

Your segfault occurs whilst assembling your argument array. Try this instead:
arg_p[0] = chrp;
chrp2 = strchr(argv[a+1], ',');
int b = 1;
while (chrp2 != NULL) {
*chrp2 = '\0';
arg_p[b++] = chrp2 + 1;
chrp2 = strchr(chrp2 + 1, ',');
}
Also note that your arg_p array is declared locally to that block and will cease to exist after that block. You may want to declare a char** arg_p pointer and malloc the space. Remember to free it at the end.

When you increment 'a' by 2, you're going to go off the end of the argv array. You only want to increment by 1 because it's indexing the words in the command line (separated by spaces) not the characters.

Related

two dimensional array increement

I need to bin a hist variable like this, which is in a loop for p and bin,
hist[p][bin] = hist[p][bin] + 1;
When I comment this line, the code works( verified the p and bin variable print). However when I include this line the program terminates with segmentation fault. Further examining the bin variable gives me a huge negative integer ( -214733313 ), which leads to segmentation fault. The program runs normally when I comment this line and the bin variables are normal integer. Do I miss an obvious thing here?.
Thanks
If you're getting a -2147... you are basically reaching the max size of a signed integer, or 2^31 -1 (32 bits, 4 bytes, a C int).
If we assume this, then it's safe to say you're hitting memory where $FFFFFFFF is in it. I only ever see this in unallocated, generally random memory. It could be safe to assume then you are going out of bounds with your ask. You could have hist[p][bin] be the maximum memory of your array, and adding 1 is going out bounds.

Segmentation Fault & printing an array without loops

I'm Just trying to run a simple program to count the number of spaces, digits and other characters using arrays. Below is my program:
void main(){
int digit_holders[10]={0};
int ch;
int i, white_space=0,other=0;
while((ch=getchar())!=EOF){
if(isspace(ch))
white_space++;
else if(isdigit(ch))
digit_holders[ch-'0']++;
else
other++;
}
digit_holders[12]=20;
printf("\n White spaces=%d\n Other=%d\n",white_space,other);
for(i=0;i<=9;i++)
printf("\ndigit_holders[%d]=%d\n",i,digit_holders[i]);
printf("\n digit_holder[12]=%d\n",digit_holders[12]);
}
2 Questions:
Why does digit_holders[12] still manage to print the assigned vale despite it being outside the range? Why doesn't it display a segmentation fault ?The same happens when I change the for loop check to i<=11 it manages to print digit_holders[11]=0 ( which it shouldn't) .. however when I replace 11/10 with 1100 i.e digit_holders[1100] in either of the case, the program crashes ( segmentation fault). Why so ?
Is there an easier way to print the elements of this array without using for loop ?
-Thanks!
There is no range checking in C so it gives it is best shot (I.e enough rope to hang yourself and the rest of the family).
Segmentation fault occurs from the OS. i.e. trying to access memory not assigned to the process.
As I wrote in the comment:
You will need a loop of some kind to print the content of your array in C.
You are assigning the 13th element of an array with only 10 elements declared, its risky to do and will be unstable, but wont necessarily result in a seg fault because if the OS hasnt modified it in the time between write and read, your pointer will resolve the value without error. But again, risky.
If you had declared an array with 13 elements, all 13 will be reserved in memory and there will be no chance of a seg fault. You are likely to get a seg fault if you interrogate an array outside of its declared limits, more so the further you go away from the range you defined.
It's possible to print "out-of-range" array indices in C because digit_holders[12] is handled as though digit_holders were a pointer with an offset of 12 * sizeof(int) added on to it.
This won't necessarily cause a segmentation fault, since the memory address being read might still be earmarked as being "available" to the program. A good example of this is a struct containing an array:
typedef struct {
int some_array[12];
int another_int;
} my_struct;
If you were to read the value of some_array[12], you'd get the contents of another_int instead, since it's stored directly after the last "valid" index of some_array.
As for the printing out of arrays: I'm not aware of any way to print out an array without using a loop in C, though it is possible in some other languages. For example, you could easily print out a list of strings in Python using print(", ".join(["This", "That", "The other"]))

Uninitialized local variable in C

I am learning C and found a similar question on a website.http://www.careercup.com/question?id=5707884834848768
I tried to understand it by writing my own program
int main()
{
int i;
printf("%d\n", i);
int *ptr = &i;
int**ptr2= &(ptr);
return 0;
}
When the two pointer assignments are commented out, the output of this program is a random garbage value each time it is executed.
If I uncomment the first pointer assignment, the output is always a fixed value (134513705).
If I uncomment the second pointer assignment, the output is always 0.
I tried to understand it by using size command for a.out
text data bss dec
1141 252 8 1405
1157 256 8 1421
1157 256 8 1421
So, even though data values are same in 2nd and 3rd cases, the output is different.
Why is the output having different values in the three cases?
As you can tell from the comments the expected output of this program is undefined. The reason for this is that the variable i was never initialized. Commenting out or adding back the pointer declarations is a bit of a red herring. Your printf statement renders the memory that 'i' is using in whatever state it is found. Running this on ideone.com outputs 0 regardless of what lines I comment in or out. Likely this is because they clear the memory before code execution. You could probably even change the output with different compiler options. The takeaway is that an uninitialized variable is a view on uninitialized memory and doesn't have a defined value.

Segmentation fault in file parsing code

I am getting a segmentation fault when I try to run my program that does matrix addition. I am trying to run the program separately ~1000 times (while timing each run and writing the result to a file).
The problem is, I get segmentation fault after a number of runs - how far I get depends on the size of the matrix. For example, if I run a 10x10 matrix (each instance has randomly generated numbers), I get segmentation fault after exactly 1013 runs. For a 100x100 matrix, I get a segfault at 260 runs.
A quick run through of how the program works is as follows:
Numbers are randomly generated and written to a file depending on the entered input (10x10, 100x100)
The numbers are read in from the file and send to CUDA*
CUDA calculates the results and writes it to a results file (and also times how long the calculation took and writes it to another file)
*This step appears to be causing the segmentation fault according to the GDB debugger. Below is the error output from the debugger and the function that is causing the error.
>Program terminated with signal 11, Segmentation fault.
#0 0x0000000000402f4c in readFromFile(int, char, int&, int&, float*) ()
Here is the actual function:
void readFromFile(int fd, char byte, int &matrixWidth, int &matrixHeight,float *matrix)
{
int tokenIndex = 0;
char *token = (char*) malloc(500);
int matrixIndex = 0;
while(read(fd,&byte,1)){
if(isdigit(byte)||byte=='.'){
token[tokenIndex]=byte;
tokenIndex++;
}
else if(byte==' ' && matrixHeight==0){
matrixWidth++;
token[tokenIndex]='\0';
matrix[matrixIndex]=atof(token);
//printf("Stored: %d\n",matrixOne[matrixIndex]);
tokenIndex=0;
matrixIndex++;
}
else if(byte=='\n'){
matrixHeight++;
if(tokenIndex!=0){
token[tokenIndex]='\0';
matrix[matrixIndex]=atof(token);
//printf("Stored: %d\n",matrixOne[matrixIndex]);
tokenIndex=0;
matrixIndex++;
}
}
else if(byte==' ' && matrixHeight!=0){
token[tokenIndex]='\0';
matrix[matrixIndex]=atof(token);
tokenIndex=0;
matrixIndex++;
}
//printf("Token: %s, number matrix: %f\n" , token, matrix[matrixIndex-1]);
}
}
This code is repeatedly run until the segmentation fault (each time the file it reads has different numbers). If you need any more code, just let me know. Any help would greatly be appreciated.
There are many problems that could cause the segmentation fault in the code you posted. Let me list a few:
As Jens pointed out how sure are you that the size of any token is actually < 500 characters
How sure are you that there are no run-on numbers like 1.32.4? ATOF could crash on this so use strtod instead
Use a debugger to run the program as macs pointed out that will give you the line that it crashed on and you can see the values of the variables so it gives you a better idea
Use safety checks when reading the input as the run-on numbers could be the least of the problems. Multiple '\n' characters could mess it up.
Since everything is text I would suggest you read using fscanf rather then building your own version.
Read up on Row major vs. Column Major formats depending on what the data might be you may not need to keep track of dimensions
How do you allocate the memory for the matrix? Equally important, do you free it? Anyway, a hint: compile your program with -g option to generate debug information, and learn how to use a debugger. Then you will find the problem, whereas we can just guess.

Coredump when parsing chapters

I am doing a homework assignment that reads in a book. First, a line is read in and a pointer made to point at that line. Then a paragraph function reads in lines and stores their address into a array of pointers. Now, I am on reading a chapter (a paragraph recognized by the next line being broke). It should call get_paragraph() and store the address of paragraphs until it comes to a new chapter.
A new chapter is the only time in the book where the first character in the line is not a space. I think this is were I am having problems in my code. All functions up to this point work. I hope I have provided enough information. The code compiles but core dumps when started.
I am a student and learning so please be kind. Thanks.
char*** get_chapter(FILE * infile){
int i=0;
char **chapter[10000];//an array of pointers
// Populate the array
while(chapter[i]=get_paragraph(infile)) { //get address store into array
if(!isspace(**chapter[0])){ //check to see if it is a new chapter<---problem line?
// save paragraph not used in chapter using static to put into next chapter
break;
}
i++;//increment array
}
//add the null
chapter[++i]='\0';//put a null at the end to signify end of array
//Malloc the pointer
char**(*chap) = malloc(i * sizeof(*chap));//malloc space
//Copy the array to the pointer
i=0;//reset address
while(chapter[i]){//while there are addresses in chapter
chap[i] = chapter[i++];//change addresses into chap
}
chap[i]='\0';//null to signify end of chapter
//Return the pointer
return(chap);//return pointer to array
}
For those who would rather see without comments:
char*** get_chapter(FILE * infile){
int i=0;
char **chapter[10000];
while(chapter[i]=get_paragraph(infile)) {
if(!isspace(**chapter[0])){
break;
}
i++;
}
chapter[++i]='\0';
char**(*chap) = malloc(i * sizeof(*chap));//malloc space
i=0;
while(chapter[i]){
chap[i] = chapter[i++];
}
chap[i]='\0';
return(chap);
}
Comments inline.
char*** get_chapter(FILE * infile) {
int i=0;
// This is a zero length array!
// (The comma operator returns its right-hand value.)
// Trying to modify any element here can cause havoc.
char **chapter[10,000];
while(chapter[i]=get_paragraph(infile)) {
// Do I read this right? I translate it as "if the first character of
// the first line of the first paragraph is not whitespace, we're done."
// Not the paragraph just read in -- the first paragraph. So this will exit
// immediately or else loop forever and walk off the end of the array
// of paragraphs. I think you mean **chapter[i] here.
if(!isspace(**chapter[0])){
break;
}
i++;
}
// Using pre-increment here means you leave one item in the array uninitialized
// which can also cause a fault later on. Use post-increment instead.
// Also '\0' here is the wrong sort of zero; I think you need NULL instead.
chapter[++i]='\0';
char**(*chap) = malloc(i * sizeof(*chap));
i=0;
while(chapter[i]) {
// This statement looks ambiguous to me. Referencing a variable twice and
// incrementing it in the same statement? You may end up with an off-by-one error.
chap[i] = chapter[i++];
}
// Wrong flavor of zero again.
chap[i]='\0';
return(chap);
}
Can I suggest that you use for loops instead of whiles? You need to stop if you run out of space, so you might as well use the appropriate construct.
I suspect you have a bug in this code:
while(chapter[i]=get_paragraph(infile)) {
if(!isspace(**chapter[0])){
break;
}
i++;
}
chapter[++i]='\0';
Firstly, shouldn't it be chapter[i] instead of chapter[0]? You want to know if the pointer at chapter[i] points to a space, not the first pointer in chapter. So this will probably loop indefinitely - hence the need for a for loop, so you don't just loop forever accidentally.
Secondly, you increment i at the end of the while block, and then again in the chapter[++i] assignment. i has already been incremented by the final loop execution before the while condition breaks, so it is already the correct position to use. ++i increments before yielding the value, so presumably you meant to have i++ here, so that it would increment after yielding the current value of i. Either way, it's confusing one of us as to what you mean, so maybe just put the increment on a separate line for clarity. The compiler will sort out any available optimisation.
Finally (and I might well be wrong here) why are you setting the value to '\0'? That's a null character, isn't it? But your array is of pointers. The null pointer would be 0, rather than '\0', I think. If I'm right, you might have still got away with it if '\0' yields the same set of zeroes as the null pointer.
Have you tried single stepping though it in gdb, and occasionally dumping the local variables to see the current state? It's a good way to learn. You may want to add a few extra intermediate variables that "info locals" will automatically dump as well (pointers to the current XXX, where XXX is various items in your hierarchy)
I assume a GNU environment:
% gcc -g homework.c -o hw
% gdb hw
(gdb) b 10
(gdb) r
(gdb) info locals
(gdb) n
(gdb) info locals
...
Replace "10" with a suitable line number near the beginning of the function.
Shouldn't it be:
if(!isspace(**chapter[i])){
Each chapter[i] is a pointer to a pointer to a char, this char is the first character in each chapter. So **chapter[i] represents the first character in chapter i. Using chapter[0] will only look at the first chapter.

Resources