So I've written a code for a simple reverse Polish calculator that works only for positive numbers using command line arguments. It stores the numbers in a stack. The functions for push and pop are in a separate source file.
I've also written another program, to check the control flow of my previous program.
Here's the first program:
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
void push(double);
double pop(void);
int main(int argc, char *argv[])
{
int c;
double op2;
while(--argc>0 && (c=(*++argv)[0]))
if(isdigit(c))
push(atof(argv[0]));
else if(c=='+')
push(pop()+pop());
else if(c=='-')
{
op2=pop();
push(pop()-op2);
}
else if(c=='*')
push(pop() * pop());
else
{
op2=pop();
push(pop()/op2);
}
printf("\n%f\n", pop());
return 0;
}
After I run this program, all the operators work, except '*'. For instance, if my input is ' ./pcalc 2 3 * ', then this is the output I get:
error: stack emptyerror: stack emptyerror: stack emptyerror: stack empty
-nan
If I interchange the conditions in the while loop, like this
while((c=(*++argv)[0]) && --argc>0)
then I get a 'segmentation fault (core dumped)' message for all operators.
To know the control flow of my program, I changed a part of the code to this:
while(--argc>0 && (c=(*++argv)[0]))
if(isdigit(c))
printf("\nentry1\n");
else if(c=='+')
printf("\nentry2\n");
else if(c=='-')
printf("\nentry3\n");
else if(c=='*')
printf("\nentry4\n");
else
printf("\nentry5\n");
The rest of the program was similar to the first one. On giving input as ' ./pcalc 2 3 * ', I get this output:
entry1
entry1
entry5
entry5
entry5
entry5
entry5
error: stack empty
0.000000
This means that control didn't go to the case for asterisk, and instead went to the else part.
When I interchange the conditions of the while loop, the output I get is similar as above( for all the operators, it shows the control flow, and for '*', it shows the same error as above), except, that it doesn't show the stack empty error for any operator, and shows instead a segmentation fault (core dumped) message.
So this is what I want to ask:
1) My first program worked for all operators, except '*'. What could be the reason? Why did the control go to the else part?
2) After interchanging the conditions, what memory was I accessing that I didn't have permission to? If it was NULL, then shouldn't that break the while loop anyway and proceed?
PS. This is my first question, so if there are any errors in my writing style, or if the question is too long, kindly let me know! We learn from our mistakes :)
Also, my compiler-GCC, OS-Ubuntu.
User xing is absolutely right.
To expand on it, the && operator is evaluated from left to right. If the left condition is not valid, then the right condition will not be evaluated as the return value is already known to be 0 (false).
Running ./pcalc 2 3 * will be expanded to ./pcalc 2 3 <all the files/directories in current working directory> so it will never push an operator on the operators' stack.
while(--argc>0 && (c=(*++argv)[0])) will first check if it is still within the arguments array before extracting the first element.
while((c=(*++argv)[0]) && --argc>0) will first try to extract a value, then check if it is still within the boundaries of the array. If not, well it has already segfaulted.
Related
This is for a school project I'm working on, it's just a small part of the code but for some reason the program doesn't seem to go inside the if() no matter what the input is. I've tried anything and everything I know of (also used the isalpha() function) but it just won't run the commands inside the if().
do
{
flag=1;
gets(input.number);
printf("\n%s\n",input.number);
for(i=0;i<strlen(input.number);i++)
{
printf("yolo1\n"); //debug
if(input.number[i]<48 || input.number[i]>57) //PROBLEM HERE
{
printf("\nyolo2\n"); //debug
flag=-1;
break;
}
}
if(strlen(input.number)<1000 || strlen(input.number)>9999 || flag==-1) printf("\nINVALID INPUT\n\nARI8MOS: ");
}while(strlen(input.number)<1000 || strlen(input.number)>9999 || flag==-1);
Can you guys help me out here??? I've been staring and the code for the better part of 3 days now....
I presume you declared char input.number[].
Your condition in if says that you only want to get into its body if the character is NOT a digit. This is somehow contradictory to the name input.number of the variable (but perhaps you are just checking for incorrect characters here...)
To better see what is happening with the condition, you can choose to print the values of its components, like this:
printf("%c[%d]", input.number[i], input.number[i]);
printf("%d, %d, %d\n", input.number[i]<48 , input.number[i]>57, input.number[i]<48 || input.number[i]>57);
(you will se a 0 for false and 1 for true)
BTW: You could write the same condition in a more readable manner, using char constants like this:
input.number[i]<'0' || input.number[i]>'9')
Here is a C function that segfaults:
void compileShaders(OGL_STATE_T *state) {
// First testing to see if I can access object properly. Correctly outputs:
// nsHandle: 6
state->nsHandle = 6;
printf("nsHandle: %d\n", state->nsHandle);
// Next testing if glCreateProgram() returns proper value. Correctly outputs:
// glCreateProgram: 1
printf("glCreateProgram: %d\n", glCreateProgram());
// Then the program segfaults on the following line according to gdb
state->nsHandle = glCreateProgram();
}
For the record state->nsHandle is of type GLuint and glCreateProgram() returns a GLuint so that shouldn't be my problem.
gdb says that my program segfaults on line 303 which is actually the comment line before that line. I don't know if that actually matters.
Is gdb lying to me? How do I debug this?
EDIT:
Turned off optimizations (-O3) and now it's working. If somebody could explain why that would be great though.
EDIT 2:
For the purpose of the comments, here's a watered down version of the important components:
typedef struct {
GLuint nsHandle;
} OGL_STATE_T;
int main (int argc, char *argv[]) {
OGL_STATE_T _state, *state=&_state;
compileShaders(state);
}
EDIT 3:
Here's a test I did:
int main(int argc, char *argv[]) {
OGL_STATE_T _state, *state=&_state;
// Assign value and try to print it in other function
state->nsHandle = 5;
compileShaders(state);
}
void compileShaders(OGL_STATE_T *state) {
// Test to see if the first call to state is getting optimized out
// Correctly outputs:
// nsHandle (At entry): 5
printf("nsHandle (At entry): %d\n", state->nsHandle);
}
Not sure if that helps anything or if the compiler would actually optimize the value from the main function.
EDIT 4:
Printed out pointer address in main and compileShaders and everything matches. So I'm gonna assume it's segfaulting somewhere else and gdb is lying to me about which line is actually causing it.
This is going to be guesswork based on what you have, but with optimization on this line:
state->nsHandle = 6;
printf("nsHandle: %d\n", state->nsHandle);
is probably optimized to just
printf("nsHandle: 6\n");
So the first access to state is where the segfault is. With optimization on GDB can report odd line numbers for where the issue is because the running code may no longer map cleanly to source code lines as you can see from the example above.
As mentioned in the comments, state is almost certainly not initialized. Some other difference in the optimized code is causing it to point to an invalid memory area whereas the non-optimized code it's pointing somewhere valid.
This might happen if you're doing something with pointers directly that prevents the optimizer from 'seeing' that a given variable is used.
A sanity check would be useful to check that state != 0 but it'll not help if it's non-zero but invalid.
You'd need to post the calling code for anyone to tell you more. However, you asked how to debug it -- I would print (or use GDB to view) the value of state when that function is entered, I imagine it will be vastly different in optimized and non-optimized versions. Then track back to the function call to work out why that's the case.
EDIT
You posted the calling code -- that should be fine. Are you getting warnings when compiling (turn all the warnings on with -Wall). In any case my advice about printing the value of state in different scenarios still stands.
(removed comment about adding & since you edited the question again)
When you optimize your program, there is no more 1:1 mapping between source lines and emmitted code.
Typically, the compiler will reorder the code to be more efficient for your CPU, or will inline function call, etc...
This code is wrong:
*state=_state
It should be:
*state=&_state
Well, you edited your post, so ignore the above fix.
Check for the NULL condition before de-referencing the pointer or reading it. If the values you pass are NULL or if the values stored are NULL then you will hit segfault without performing any checks.
FYI: GDB Can't Lie !
I ended up starting a new thread with more relevant information and somebody found the answer. New thread is here:
GCC: Segmentation fault and debugging program that only crashes when optimized
I have tried so many things. Running from command line, running from cmd, running with /K, putting system("pause"); getchar(); getch(); before return 0 and I simply can't get it to run. I'm writing in Notepad++, compiling in Cygwin and the window appears blank for the split second it appears (according to my screenshot, it could have been taken too early). Basically I've tried anything I could Google myself to. So I figured it must be something wrong with my code that the debugger doesn't show.
#include <stdio.h>
int main()
{
float lt1, lt2, dmg, x;
lt1=10;
lt2=30;
while(lt2>dmg)
{
while(x>0 || lt2>dmg)
{
dmg=dmg+x*lt1;
x--;
return (dmg);
}
x=x+0.01;
return (x);
}
printf("Horde factor is: %f", x);
return 0;
}
I would appreciate any help I can get, and I hope you will bear over with my inexperience.
You have undefined behavior in your code.
When you declare a local variable without assigning anything to it, its value is indeterminate. Usage of this variable will be undefined behavior until you assign a value to it.
In this case it's the dmg and x variables that causes this problem.
Its because of these statement :
return (dmg); //this ends the code execution .. because you have returned something from main()
x=x+0.01;
return (x); // even this one is wrong
you are exiting the code there and never getting to the printf ..
there should only be one return in main() .. and at the end.
More problems with your code:
you don't initialise dmg and x , but you use them as parameters for while loop
float lt1, lt2, dmg, x; // dmg,x uninitialized
In the outer while loop .. its an infinite loop as you don't do anything to the parameters of that loop to get out of it.
Like I said above .. there should be only 1 return in main()
Maybe instead of returning you should look into break; ( i don't know if thats what you want or not as I don't understand your code )
i was practicing my C Prog Language
and i decided to create a salon with cashier features
it looks messy,
though i'm still learning
posted here: http://pastebin.com/B2XaaCYV
it say runtime error with variable "menu", but i tried to recheck it around 5x and i don't see any error with it.
the code is really simple
like xy[0][1] = default 0 = meaning not yet purchased. its value will be 0/1 only. it will be 1 when you actually purchase it after picking the hairstyle.
then of course
xy[1][i] means price of xy[0][i]
i tried using other techniques like removing of breaks and changing variable name, but still it says runtime error with variable menu
no idea what makes the error. so i wish someone can help me with this
scanf("%1s",&menu);
No! A char isn't a string at all. You want to get a single character, so use either getchar() or scanf("%c",&menu);.
A related error is in your core_return, where you try to read 3 characters into a single character. Also, don't call your main in a sub-routine. Instead return from the sub-routine and put a loop in your main. By the way, 'yes' and 'no' aren't valid. If you want to compare strings, you have to use strcmp:
// returns 1 if the user wants to go again
int another_menu(void)
{
char tmp[20];
printf("Do you want another service?");
for(;;){
scanf("%3s",tmp);
if(strcmp("y",tmp) || strcmp("yes",tmp))
return 0;
else if(strcmp("n",tmp) || strcmp("no",tmp))
return 1;
printf("Please specify either 'no' or 'yes': ");
}
}
Use compiler warnings in order to find your errors quicker (GCC: -Wall -Wextra).
Hello I am studying for a test for an intro to C programming class and yesterday I was trying to write this program to print out the even prime numbers between 2 and whatever number the user enters and I spent about 2 hours trying to write it properly and eventually I did it. I have 2 pictures I uploaded below. One of which displays the correct code and the correct output. The other shows one of my first attempts at the problem which didn't work correctly, I went back and made it as similar to the working code as I could without directly copying and pasting everything.
unfortunately new users aren't allowed to post pictures hopefully these links below will work.
This fails, it doesn't print all numbers in range with natural square root:
for (i = 2; i <= x; i++)
{
//non relevant line
a = sqrt(i);
aa = a * a;
if (aa == i);
printf("%d ",i);
}
source: http://i.imgur.com/WGG6n.jpg
While this succeeds, and prints even numbers with natural sqaure root
for (i = 2; i <= x; i++)
{
a = sqrt(i);
aa = a * a;
if (aa == i && ((i/2) *2) == i)
printf("%d ", i);
}
source: http://i.imgur.com/Kpvpq.jpg
Hopefully you can see and read the screen shots I have here. I know that the 'incorrect code' picture does not have the (i/2)*2 == i part but I figured that it would still print just the odd and even numbers, it also has the code to calculate "sqrd" but that shouldn't affect the output. Please correct me if I'm wrong on that last part though.
And Yes I am using Dev-C++ which I've read is kinda crappy of a program but I initally did this on code::blocks and it did the same thing...
Please I would very much appreciate any advice or suggestions as to what I did wrong 2 hours prior to actually getting the darn code to work for me.
Thank you,
Adam
your code in 'that' includes:
if (aa == i);
// ^
printf(...);
[note the ; at the end of the if condition]
Thus, if aa == i - an empty statement happens, and the print always occures, because it is out of the scope of the if statement.
To avoid this issue in the future, you might want to use explicit scoping1 [using {, } after control flow statements] - at least during your first steps of programming the language.
1: spartan programmers will probably hate this statement
Such errors are common. I use "step Over", "Step Into", "Break Points" and "watch window" to debug my program. Using these options, you can execute your program line by line and keep track of the variables used in each line. This way, u'll know which line is not getting executed in the desired way.