Variable loses its value C - c

I'm working on this project where a user has to guess a word (wordToGuess) and he has a number of attempts.
The problem is that the variable "wordToGuess" loses its value when the code arrives in the point marked ("HERE LOSES ITS VALUE). I don't know how to solve this problem, I've tried in many ways. Thank u for your help!
(checkExistence is a function that checks if the word is present in the dictionary)
void newGame(node* head){
char wordToGuess[10];
char attempt[10];
int numberOfAttempts = 0;
if (scanf("%s" , wordToGuess) != 1){
printf("error1");
}
getchar();
if (scanf("%d", &numberOfAttempts) != 1){
printf("error2");
}
getchar();
while(numberOfAttempts > 0){
if (scanf("%s", attempt) != EOF){
if (attempt[0] != '+'){
if (checkExistence(head, attempt) == false){
printf("not_exists\n");
}else{
if (strcmp(wordToGuess, attempt) == 0){
printf("ok\n");
return;
}else{
//code
numberOfAttempts--;
}
}
}else{
if (attempt[0] == '+' && attempt[1] == 's'){
//HERE LOSES ITS VALUE
}else if (attempt[0] == '+' && attempt[1] == 'i'){
//other code
}
}
}else{
printf("ko");
return;
}
}
return;
}
Here a test case:
2rj9R (wordToGuess)
18 (numerAttemps)
DP3wc (attempt)
7PGPU (attempt)
2rz9R (attempt)
+print_list (from this point I lose the value of wordToGuess)
2rj9R (attempt)

As the others have point, you're probably causing a buffer overflow in your attempt buffer which overwrites your wordToGuess buffer since your attempt and wordToGuess buffer is stored like this in your memory:
<attempt buffer> | <word To Guess>
You have two possible fixes for this (as the comments have said...):
A little fix would be to set a limit of how many characters should be read from stdin to scanf like this:
scanf("%9s" , wordToGuess) // you need 9, because your buffer can store up to
// 10 bytes but don't forget that `scanf` is also
// addinng `\0` for you!
and don't forget to flush the rest of the user input if you want that the user should be only able to insert at most 9 characters!
Increase the buffer size of your attempt (and wordToGuess) buffer but also add those read-limits for scanf which is described in the first point.

At the indicated point of the code where wordToGuess appears to lose its value, it is a dead variable. If you're looking at optimized code in a debugger, you may find that the variable doesn't exist there any more.
At a given point in a program, a dead variable is one which is never used past that point. All control flows out of that point reach the termination of that code, without ever using the variable again. Simple example:
{
int x = 3;
// x is live here: there is a next reference
printf("%d\n", x);
// x is now dead: it is not referenced after the above use
printf("foo\n");
}
In the generated code, the compiler may arrange to re-use the resources tied to a dead variable as soon as it is dead: give its register and memory location to something else.
In the debugger, if we put a breakpoint on the printf("foo\n") and try to examine x, we might get a strange result.
To have the best chance of seeing the expected result (that x still exists, and is retaining its most recent value), we have to compile with optimizations disabled.

Related

curses move backwards accounting for previous lines

Is there any way to move the cursor backwards while accounting for previous lines, i.e. when the cursor goes back from the beginning of the line it goes to the last non-empty character of the previous line?
So there's no built in method for this, so I had to write my own
void backspace(){
int x,y;
getyx(stdscr,y,x);
if(x == 0) {
if( y == 0 ) {
return;
}
x = getmaxx(stdscr) - 1;
move(--y,x);
char ch = ' ';
while(ch == ' ' && x != 0){
move(y,--x);
ch=inch();
}
} else {
move(y,x-1);
}
delch();
}
Note that I have removed some irrelevant file I/O related code that was in this method.
You can do that easily in a curses (full-screen) application (by reading the characters from the virtual screen using winch or win_wch), but would find it much harder in a termcap/terminfo low-level application because there is no portable method for reading directly from the terminal's screen.

C - segmentation fault when comparing integers

here is a part of my code. When I run my code, it's requesting an input from user and then matching it with another integer which recorded in my structure. When user input is matching, it is working correct. But when user enters a wrong input, it gives a segmentation fault. In where, I should make changes on my code?
long int userInput,endCheck; // Input from user
int flag=0; // check for match
int status;
int c; // controlling ctrl+D
int position= 999; // position of where the user input and data matched
LABEL:
printf("\n\t---------------------------------------\n");
printf("\n\nPlease enter the student ID which you want to find(3-times CTRL+D for finish):\n");
scanf("%d",&userInput);
if( (c=getchar()) == EOF){
exit(0);
}
for(i=0;i<lines,flag==0;i++){
if(index[i].id == userInput){
position=i;
flag=1;
}else{
position=999;
}
}
if(flag==0){
printf("id not found");
}
studentInfo info; // for storing the information which we will take between determined offsets
if(position!= 999){
if ( (pos = lseek(mainFile,index[position].offset , SEEK_SET)) == -1)/*going to determined offset and setting it as starting offset*/
{ perror("classlist"); return 4; }
while ( (ret= read(mainFile,&info, sizeof(info))) > 0 ){
printf("\n\nStudent ID: %d, Student Name: %s\n\n",info.id,info.name);
break;// to not take another students' informations.
}
}
flag=0;
goto LABEL;
printf("Program is terminated");
The right way to do that loop with the unwanted comma is like this. When you find the right index[i].id you can exit the loop early by using break.
for(i=0;i<lines;i++){
if(index[i].id == userInput){
position=i;
flag=1;
break;
}
}
You don't need the else branch as position is set to 999 from the outset of the code. But really you shouldn't use position in this fashion. What if you have more than 999 records? You're already using flag to identify if you've set position to a valid value. You should replace any instance of if(position!= 999) with if(flag).
Or since position is a signed int, you could use a negative value and ditch the flag.
The reason can be the fact that you are reaching an index that doesn't exist in the end of cycle, in the moment of the "if" statement with iterator "i".
Or in the last if, where you access a "position" index of the array. Check those limits.
Also, try GDB, is useful for solving this kind of problems.

Parameters inside the function

I have a work to do in which I have to keep a loop inside the function expecting the following parameters:
-"i" to insert
-"s" to search
-"q" to quit
How do I keep this loop? I've looked up some options and it seems to be possible using a while or a switch, but I am not sure which is the best way to read those chars (with a fscanf perhaps?). I am also not sure how to read the things after the parameter "i" as the input would be "i word 9", so after detecting the i to insert I have to read a string and an int.
Anyone has any idea how to do this? I am sorry is this seems simple, but I am new to programming.
edit: Here is what I have so far
while (loop) {
fscanf(stdin,"%c",&par);
if (strcmp(&par,"i")){
scanf("%s %d",palavra,p);
raiz = insere(raiz,&palavra,p);
}
else if (strcmp(&par,"b")){
scanf("%s",palavra);
busca(raiz,&palavra);
}
else if (strcmp(&par,"q"))
loop = 0;
}
edit 2: This is what I have now, I am having problems reading the string and integer when the parameter is i, somehow it crashes the function
while (1) {
c = getchar();
if (c == 'f')
break;
else if (c == 'i'){
fscanf(stdin,"%s",&palavra);
scanf("%d",&p);
raiz = insere(raiz,palavra,p);
}
else if (c == 'b') {
scanf("%s",palavra);
busca(raiz,palavra);
}
}
Thanks in advance!
The code you have doesn't look too bad compared to what I believe you want. You can replace the "while (loop)" with "while (1)" and then your exist code "loop = 0;" with "break;" which is a bit more standard way of doing things. Also "fscanf(stdin..." is the same as "scanf(..." ... scanf will read from stdin by default. You might want to check the docs for strcmp because it returns 0 for an exact match and I don't think that will do what you want in your 'if' statements. You should be able to use scanf to read in the values you want, is it giving you an error?
You are using 3 separated scans. That means you can't input this "i word 9", but input one command or parameter at the time separated by EOL(pressing enter).. i, enter, word, enter, 9, enter ... Then the function should actually get further in those "if"s. With those scans you also should consider printing information about expected inputs ("Choose action q/i/f")
And I would recommend using something to test those inputs.
if (scanf("%d", &p) == 0) {
printf("Wrong input");
break;
}

Advice on Segmentation Fault, using gdb effectively, C Programming (newbie)

I am having a problem with a segmentation fault working in C, and I cannot figure out why this is occurring. I think it has something to do with misuse of the fget(c) function.
while((ch = fgetc(fp))!= EOF) {
printf("Got inside first while: character is currently %c \n",ch); //**********DELETE
while(ch != '\n') {
char word[16]; //Clear out word before beginning
i = i+1; //Keeps track of the current run thru of the loop so we know what input we're looking at.
while(ch != ' ') {
printf("%c ",ch); //**********DELETE
//The following block builds up a character array from the current "word" (separated by spaces) in the input file.
int len = strlen(word);
word[len] = ch;
word[len+1] = '\0';
printf("%s",word);
ch = fgetc(fp);
}
//The following if-else block sets the variables TextA, TextB, and TextC to the appropriate Supply Types from the input.
//This part may be confusing to read mentally, but not to trace. All it does is logically set TextA, B, and C to the 3 different possible values SupplyType.
if(word!=TextB && word!=TextC && i==1 && TextB!="") {
strcpy(TextA,word);
}
else if(word!=TextA && word!=TextC && i==1 && TextC!="") {
strcpy(TextB,word);
}
else if(word!=TextB && word!=TextA && i==1) {
strcpy(TextC,word);
}
switch(i) {
case 1:
if(TextA == word) {
SubTypeOption = 1;
}
else if(TextB == word) {
SubTypeOption = 2;
}
else if(TextC == word) {
SubTypeOption = 3;
}
break;
case 2:
//We actually ultimately don't need to keep track of the product's name, so we do nothing for case i=2. Included for readibility.
break;
case 3:
WholesalePrice = atof(word);
break;
case 4:
WholesaleAmount = atoi(word);
break;
case 5:
RetailPrice = atof(word);
break;
case 6:
RetailAmount = atoi(word);
break;
}//End switch(i)
ch = fgetc(fp);
}//End while(ch != '\n')
//The following if-else block "tallys up" the total amounts of SubTypes bought and sold by the owner.
if(SubTypeOption == 1) {
SubType1OwnersCost = SubType1OwnersCost + (WholesalePrice*(float)WholesaleAmount);
SubType1ConsumersCost = SubType1ConsumersCost + (RetailPrice *(float)RetailAmount);
}
else if(SubTypeOption == 2) {
SubType2OwnersCost = SubType2OwnersCost + (WholesalePrice*(float)WholesaleAmount);
SubType2ConsumersCost = SubType2ConsumersCost + (RetailPrice *(float)RetailAmount);
}
else if(SubTypeOption == 3) {
SubType3OwnersCost = SubType3OwnersCost + (WholesalePrice*(float)WholesaleAmount);
SubType3ConsumersCost = SubType3ConsumersCost + (RetailPrice *(float)RetailAmount);
}
}//End while((ch = fgetc(fp))!= EOF)
Using gdb (just a simple run of the a.out) I found that the problem is related to getc, but it does not tell which line/which one. However, my program does output "Got in side the first while: character is currently S". This S is the first letter in my input file, so I know it is working somewhat how it should, but then causes a seg fault.
Does anyone have any advice on what could be going wrong, or how to debug this problem? I am relatively new to C and confused mostly on syntax. I have a feeling I've done some small syntactical thing wrong.
By the way, this snippet of the code is meant to get a word from a string. Example:
Help me with this program please
should give word equaling "Help"
Update: Now guys I am getting kind of a cool error (although cryptic). When I recompiled I got something like this:
word is now w S
word is now w Su
word is now w Sup
... etc except it goes on for a while, building a pyramid of word.
with my input file having only the string "SupplyTypeA 1.23 1 1.65 1" in it.
UPDATE: Segmentation fault was fixed (the issue was, I was going past the end of the file using fgetc() ). Thanks everyone.
If anyone still glances at this, could they help me figure out why my output file does not contain any of the correct numbers it should? I think I am probably misusing atof and atoi on the words I'm getting.
Make sure you compile the program with -g -O0 options
Next step through the program line by line in GDB, watch and understand what your program is doing. Look at the various variables. This is the essential debugging skill.
WHen it dies type the command 'k' this will give you a stack trace the last line of the trace will have the failing line number, but you know that anyway because you were on the line shen you did a step command
There is no "fget" in good old C, but maybe you're using a more modern version that has something named "fget". Most likely, you meant to use "fgetc". When a C I/O function starts with "f", it usually wants a FILE* handle as an argument, as "fgetc" does. Try using "fgetc" instead, after reading the documentation for it.

linux kernel + conditional statements

I basically am running into a very odd situation in a system call that I am writing. I want to check some values if they are the same return -2 which indicates a certain type of error has occurred. I am using printk() to print the values of the variables right before my "else if" and it says that they are equal to one another but yet the conditional is not being executed (i.e. we don't enter the else if) I am fairly new to working in the kernel but this seems very off to me and am wondering if there is some nuance of working in the kernel I am not aware of so if anyone could venture a guess as to why if I know the values of my variables the conditional would not execute I would really appreciate your help
//---------------------------------------//
/* sys_receiveMsg421()
Description:
- Copies the first message in the mailbox into <msg>
*/
asmlinkage long sys_receiveMsg421(unsigned long mbxID, char *msg, unsigned long N)
{
int result = 0;
int mboxIndex = checkBoxId(mbxID);
int msgIndex = 0;
//acquire the lock
down_interruptible(&sem);
//check to make sure the mailbox with <mbxID> exists
if(!mboxIndex)
{
//free our lock
up(&sem);
return -1;
}
else
mboxIndex--;
printk("<1>mboxIndex = %d\nNumber of messages = %dCurrent Msg = %d\n",mboxIndex, groupBox.boxes[mboxIndex].numMessages, groupBox.boxes[mboxIndex].currentMsg );
//check to make sure we have a message to recieve
-----------CODE NOT EXECUTING HERE------------------------------------------------
if(groupBox.boxes[mboxIndex].numMessages == groupBox.boxes[mboxIndex].currentMsg)
{
//free our lock
up(&sem);
return -2;
}
//retrieve the message
else
{
//check to make sure the msg is a valid pointer before continuing
if(!access_ok(VERIFY_READ, msg, N * sizeof(char)))
{
printk("<1>Access has been denied for %lu\n", mbxID);
//free our lock
up(&sem);
return -1;
}
else
{
//calculate the index of the message to be retrieved
msgIndex = groupBox.boxes[mboxIndex].currentMsg;
//copy from kernel to user variable
result = copy_to_user(msg, groupBox.boxes[mboxIndex].messages[msgIndex], N);
//increment message position
groupBox.boxes[mboxIndex].currentMsg++;
//free our lock
up(&sem);
//return number of bytes copied
return (N - result);
}
}
}
UPDATE: Solved my problem by just changing the return value to something else and it works fine very weird though
Please remember to use punctuation; I don't like running out of breath while reading questions.
Are you sure the if block isn't being entered? A printk there (and another in the corresponding else block) would take you one step further, no?
As for the question: No, there isn't anything specific to kernel code that would make this not work.
And you seem to have synchronization covered, too. Though: I see that you're acquiring mboxIndex outside the critical section. Could that cause a problem? It's hard to tell from this snippet, which doesn't even have groupBox declared.
Perhaps numMessages and/or currentMsg are defined as long?
If so, your printk, which uses %d, would print just some of the bits, so you may think they're equal while they are not.

Resources