Segmentation Fault & printing an array without loops - c

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"]))

Related

Array & segmentation fault

I'm creating the below array:
int p[100];
int
main ()
{
int i = 0;
while (1)
{
p[i] = 148;
i++;
}
return (0);
}
The program aborts with a segmentation fault after writing 1000 positions of the array, instead of the 100. I know that C doesn't check if the program writes out of bounds, this is left to the OS. I'm running it on ubuntu, the size of the stack is 8MB (limit -s). Why is it aborting after 1000? How can I check how much memory my OS allocates for an array?
Sorry if it's been asked before, I've been googling this but can't seem to find a specific explanation for this.
Accessing an invalid memory location leads to Undefined Behavior which means that anything can happen. It is not necessary for a segmentation-fault to occur.
...the size of the stack is 8MB (limit -s)...
variable int p[100]; is not at the stack but in data area because it is defined as global. It is not initialized so it is placed into BSS area and filled with zeros. You can check that printing array values just at the beginning of main() function.
As other said, using p[i] = 148; you produced undefined behaviour. Filling 1000 position you most probably reached end of BSS area and got segmentation fault.
It appear that you clearly get over the 100 elements defined (int p[100];) since you make a loop without any limitation (while (1)).
I would suggest to you to use a for loop instead:
for (i = 0; i < 100; i++) {
// do your stuff...
}
Regarding you more specific question about the memory, consider that any outside range request (in your situation over the 100 elements of the array) can produce an error. The fact that you notice it was 1000 in your situation can change depending on memory usage by other program.
It will fail once the CPU says
HEY! that's not Your memory, leave it!
The fact that the memory is not inside of the array does not mean that it's not for the application to manipulate.
The program aborts with a segmentation fault after writing 1000 positions of the array, instead of the 100.
You do not reason out Undefined Behavior. Its like asking If 1000 people are under a coconut tree, will 700 hundred of them always fall unconscious if a Coconut smacks each of their heads?

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 when trying to check command line arguments (in 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.

why my code has not a limit?

That is my code:
#include<stdio.h>
int main()
{
int vet[10], i;
for(i=30; i<=45; i++)
{
scanf("%d", &vet[i]);
}
for(i=30; i<=45; i++)
printf(" %d ", vet[i]);
for(i=30; i<=45; i++)
printf(" %x", &vet[i]);
return 0;
}
I declared just 10 positions of int type on memory, but i get more, so what happened ?
it is a memory overflow ?
and the type %x is correctly to print the memory adress ?
the imput was:
1
2
3
4
5
6
7
8
9
10 /*It was to be stoped right here !?*/
11
12
13
14
15
16
and returned:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 /*I put space to indent*/
22ff6c 22ff70 22ff74 22ff78 22ff7c 22ff80 22ff84 22ff88 22ff8c 22ff90 22ff94 22ff98 22ff9c 22ffa0 22ffa4 22ffa8
The C language does not check bounds when you access arrays for reading or writing. It is up to the program author to ensure that the program accesses only valid array elements.
In this case, you wrote values to memory addresses outside your declared array. While you may sometimes get a segmentation violation (SIGSEGV) in this case, you may just get "lucky" -- really, unlucky -- and not encounter any problems at runtime.
C doesn't enforce array boundaries. Keeping within the limits is your responsibility in that language - it will let you do plainly wrong things, but it may crash at runtime.
Not only does the C language not check bounds on array accesses with respect to array size, which explains why you are successfully writing to the array 15 times, but C also does not have a mechanism for converting your range of 30 to 45 into the range of the first 10 (or 15?) elements of the array.
So, you are really attempting to write to the 31st through 46th element of the array vet, which has only 10 elements.
C is perfectly happy to let you read from and write to an array past the bounds you set (10, in this case).
Reading past the limit just gives you garbage; writing past it will do all kinds of crazy things and generally crash your program (or, if you are unlucky, overwrite your entire hard drive).
You were lucky with this program, but you should not keep doing that. In C, you are responsible for enforcing the limits of your arrays yourself.
int vet[10] declares a block of ten integers in memory. These memory locations are accessed via vet[0] through vet[9]. Any other access to memory through vet is undefined behavior. Absolutely anything could be within that memory, and you can easily corrupt the rest of your program execution. The compiler trusts you to know better than what you were doing.
As #NigelHarper correctly points out, %p is the official way of printing pointers. It prints in hexadecimal. Pointers could print in decimal, but the number itself is meaningless. Hexadecimal makes the printing more concise, and just as easy to see differences from one address to the next.
It is also possible to use %x for printing a pointer, since all that does is take a value and print it in hexadecimal form.
C does not do bounds checking on arrays and you are accessing an array out of bounds. The possible valid indexes in the array are [0,9], but you are accessing [30,45].
You should modify your code to only access valid indexes:
int SIZE = 10;
int vet[SIZE];
//...
// not for( i = 30; i <= 45; i++ )
for( i = 0; i < SIZE; ++i ) { /* ... */ }
C Language doesn't have support to check the out of bound array accesses. IN c++, if you try to access out of bound array memory location, it will generate Segmentation Fault which causes your process to terminate. As, C doesn't allow it, it is expected behavior.

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.

Resources