I am trying to write a c program to monitor the temperatures of my processor.
To test my program I read integers from a file using fscanf. To my surprise this does not work under certain conditions.
I am using the following code:
#include <stdio.h>
#define CORECOUNT 3
int main()
{
int c=0;
int core[CORECOUNT]={0};
FILE *cmd[CORECOUNT];
for (c=0; c<=CORECOUNT; c++) //read input and store it in 'core'
{
cmd[c]=fopen("testinput", "r");
printf("c=%d\n", c);
fscanf(cmd[c], "%d", &core[c]);
printf("core[c]=%d, z=%d\n", core[c], c);
fclose(cmd[c]);
}
for (c=0; c<=CORECOUNT; c++) //print input
{
printf("core%d: %d ", c, core[c]);
}
printf("\n");
}
It compiles without an error.
Everything works as expected until the third (and last) call of fscanf: then suddenly 'c' gets the value 42 (which 'core' should get actually):
c=0
core[z]=42, z=0
c=1
core[z]=42, z=1
c=2
core[z]=42, z=2
c=3
core[z]=1, z=42
Segmentation fault (core dumped)
The segmentation fault occurs because fclose tries to close cmd[42] which does not exist.
When using other values of 'CORECOUNT' (e.g. 4) everything works as expected. However, when using a number which has '11' as last two digits in binary (e.g. 3, 7, 11, 15, ...) the program will crash. When declaring another integer and setting it to '0' the program works as expected when 'CORECOUNT' has a value which has '11' as last two digits in binary. If this is not the case 'core' does sometimes get strange values (e.g. '15274000', which are not the same every time the program is executed).
Strange enough, this only happens in gcc 4.6.3, but not in gcc 4.8
Where is the error in my code? Or is it even something in the compiler (which I highly doubt)?
just for now I'll declare another variable ('tmp') and use it as index in the call of fscanf:
printf("c=%d\n", c);
tmp=c;
fscanf(cmd[c], "%d", &core[tmp]);
I'm sorry if there are any spelling/grammar errors; English is not my native language.
In your for loops, change c<=CORECOUNT to c<CORECOUNT
You have declared arrays of size [CORECOUNT] thus when CORECOUNT is 3, you have elements [0], [1], [2]. Having c<=CORECOUNT in your for loop, you try to access element [3] so memory outside the array is being corrupted.
Related
#include <stdio.h>
int main() {
unsigned char c = (int) 0.54;
for(; c++; printf("%d", c));
printf("%d", c);
return 0;
}
And when I run the program the output is displayed as 1
How can the output be 1? Thanks in advance
In the first line- unsigned char c=(int)0.54; char actually stores the ASCII code of the character so in another way it's an integer which stores the data in this way :
The compiler converts the number stored into the character from decimal number system to binary number system and takes into consideration only the first 8 bits from the right of that number represented in binary.(we don't need to consider the case of negative numbers since you use an unsigned char)-so as a result the variable c takes 0 as value at the end of this line.
For the second line of your code- for(;c++;printf("%d",c)); :
so we have a for loop
( for (INITIALIZATION; CONDITION; AFTERTHOUGHT))
** In the INITIALIZATION part , Leaving this empty is fine, it's just equivalent that you have already initialized the variable that you are going to use as loop variable .
** In the CONDITION part , c++ is equivalent to c++!=0. It keeps the for loop running until c++==0.(in your case c is initialized by 0 , so we will have c++=0 and the program immediately exits the for loop).
** In the AFTERTHOUGHT part , The printf is run at the end of each iteration but doesn't change the value of c.(since the condition c++!=0 is not verified the code will not write the iteration, so it will not pass to printf)
printf("%d",c); will display 1 ( c++ in your loop is used as condition and in the same time to increment variable c by 1 ; c++ post-increment operator uses the principle 'use-then-change' so , c is incremented by 1 exactly after exiting the for loop , and c becomes equal to 1).
I'm trying to teach myself C using Kernighan's book and I'm supposed to make a graph that indicates how many letters there are in each word. I haven't got to the "plotting" part as I'm getting really weird and enormous numbers at the output. Right now I'm just trying to have the value of the first and second elements of the array "arreglo" printed.
The code is the following:
#include <stdio.h>
#define ARRAY_SIZE 100
/*#define AUX 0
#define AUX2 0*/
main()
{
int s,j,noletra,i,arreglo[ARRAY_SIZE],otros, nopalabra, c;
int a;
nopalabra=1;
while((c=getchar())!=EOF)
{
if(c==' '||c=='\t'||c=='\n')
++nopalabra;
else
++arreglo[nopalabra];
}
printf("%d",arreglo[1],arreglo[2]);
}
The reason I'm trying to know the value in the second element in the array is that the first element has the correct value. The code is supposed to add 1 to the array index which is the number of words each time a space, tab or \n is typed and to add 1 to the array element whenever something different than the previously mentioned characters is typed (Letters). Right now it´s supposed to print correctly the number of the letters of two words, the first element is correctly printed but the second is a huge number, the output is:
alan amaury
^Z
4 8257542
--------------------------------
Process exited after 7.773 seconds with return value 9
Press any key to continue . . .
The output is supposed to be 4 7. I'm using a compiler in windows so EOF should be Ctrl+Z
Any help that I could get from you will be appreciated :)
At least these problems.
int arreglo[ARRAY_SIZE]; is not initialized before its elements are incremented. This is the mostly likely cause of "Why am I getting this huge numbers" #ikegami
// int arreglo[ARRAY_SIZE];
// replace with
int arreglo[ARRAY_SIZE] = { 0 };
Code can access out of array bounds as nopalabra is not confined to 0 to 99.
#define ARRAY_SIZE 100
int arreglo[ARRAY_SIZE];
++arreglo[nopalabra]; // No access protection
printf("%d",arreglo[1],arreglo[2]); only prints arreglo[1]
Logic flow is incorrect to "make a graph that indicates how many letters there are in each word."
main() return type not coded.
Some pseudo-code as an alternative
int main(void) {
set all arreglo[] to 0
int nopalabra = 0;
part_of_word = false; // Keep track of word state
loop forever {
get a character into c
if c is a separator or EOF
if (part_of_word) {
arreglo[nopalabra]++;
part_of_word = false;
nopalabra = 0;
if (c == EOF) break loop
} else {
nopalabra++;
part_of_word = true;
}
}
print out results
}
First, try the solution answered before, changing the printf() call.
If there is still a problem try:
printf("%d %d \n",arreglo[1],arreglo[2]);
Just before the while loop, to see if the "arreglo" array is initialize to 0's or just random values.
On the side:
Your call to printf() has more parameters than covered by the format string.
So you should clean up your code to something similar to
printf("%d %d\n", arreglo[1], arreglo[2]);
Concerning the strange output:
A way of getting surprising values is using non-initialised variables.
In your case the lack of initialisation affects the array arreglo.
Make sure to initialise it, so that all counting starts on a meaningful value.
Another way of getting seemingly very high values is printing several numbers next to each other, without separating white space in between.
So the " " and the "\n" in the format string I proposed are quite relevant.
the question is: "Why am I getting this huge numbers in C?"
the answer is: you have not assigned anything to arreglo array, and since you have not initialized it, you got some random values that have been there in memory. Trust me on this, I have run your code in debugger, which I also highly recommend a a standard practice while lerning to program.
Also, this is a common mistake where the format specifier is not written:
printf("%d",arreglo[1],arreglo[2]);
See if using printf("%d","%d",arreglo[1],arreglo[2]) solves your problem.
By the way, K&R book is very old, and written at the time where there have been no other C books. There are better ways to learn C.
So If I had this code:
int main() {
char buff[20];
int x = 0;
gets(buff);
if (x==1337) {
print("Congrats");
}
printf("%d\n", x);
return 0;
}
Knowing that this is written in C (not that it matters too much), how would one go about overflowing this char[] by exactly 1337?
And also, I don't really understand the output I'm getting.. For example, if I run this code and input:
12345678901234567890a
The output is:
0
In fact, I have to overflow my char[] by an additional 8 characters past my array size before the data leaks into the value for X. I have no idea why this is, and would really like some help if somebody understand that.. However, it doesn't stop there.
If my input is:
1234567890123456789012345678aa
My output is:
24929
This throws me for quite a twirl.. Since I would've expected it to either overflow by the char value of a+a or maybe even a*a, alas it is neither. (the char value of a is 97).
So to sum it up, since I now it is probably confusing.. I would like to know how to overflow a buffer (in C) into an int, leaving the int a very specific value (in this case 1337). And in addition, if you could explain how these numbers are coming out, I would greatly appreciate it! By the way, it might help to mention the code is being executed on a Linux shell.
Since this is probably homework, rather than give you a direct answer, what I'm going to do is show you the C program that does what you thought your program would do, and how it behaves when fed over-length input.
#include <stdio.h>
int main(void)
{
struct {
char buff[20];
volatile unsigned int x;
} S;
S.x = 0;
gets(S.buff);
if (S.x == 1337)
puts("Congrats");
else
printf("Wrong: %08x\n", S.x);
return 0;
}
The key difference is that I am forcing the compiler to lay out the stack frame a particular way. I am also printing the value of x in hexadecimal. This makes the output both more predictable, and easier to interpret.
$ printf 'xxxxxxxxxxxxxxxxxxxxABCD' | ./a.out
Wrong: 44434241
$ printf 'xxxxxxxxxxxxxxxxxxxxABC' | ./a.out
Wrong: 00434241
$ printf 'xxxxxxxxxxxxxxxxxxxxAB' | ./a.out
Wrong: 00004241
$ printf 'xxxxxxxxxxxxxxxxxxxxA' | ./a.out
Wrong: 00000041
Everything that confused you is caused by one or more of: the compiler not laying out the stack frame the way you expected, the ordering of bytes within an int not being what you expected, and the conversion from binary to decimal obscuring the data in RAM.
Exercise for you: Compile both my program and your original program in -S mode, which dumps out the generated assembly language. Read them side by side. Figure out what the differences mean. That should tell you what input (if any -- it might not be possible!) will get your program to print 'Congrats'.
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"]))
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.