Segmentation fault on certain inputs and not others - c

Heres a function I wrote that has some debugging elements in it already. When i enter either a "y" or a "Y" as the input I get a segmentation fault during runtime. When I enter any other value the code runs. The seg fault kicks out after it scans and gives me the response but before the "scan worked" line is output. DOn't know why it would act like this only on these values. If anyone needs the function call I have that as well.
query_user(char *response [10])
{
printf("response after query call before clear=%s\n",response);
strcpy(response,"");
printf("response after clearing before scan=%s\n",response);
printf("Enter another person into the line? y or n\n");
scanf("%s", response);
printf("response after scan=%s\n",response);
printf("scan worked");
}
main()
{
char response [10];
strcpy(response,"y");
printf("response=%s\n",response);
printf("When finished with program type \"done\" to exit\n");
while (strcmp(response,"done") != 0)
{
printf("response after while loop and before query call=%s\n",response);
query_user(&response);
}
}
output on error:
response after query call before clear=y
response after clearing before scan=
Enter another person into the line? y or n
y
response after scan=y
Segmentation Fault (core dumped)
output on non-error:
response after query call before clear=y
response after clearing before scan=
Enter another person into the line? y or n
n
response after scan=n
scan worked
Cycle number 0
(program continues to run outside this function)

Your declaration of the parameter for query_user is wrong. You've declared an array of pointers to char. You need a simple char buffer. Like this:
query_user(char response[])
or
query_user(char* response)
Use whichever you prefer.
When you call the function, you can do it like this:
query_user(response);
Also I would point out that your declaration for main is incorrect. You should use
int main(void)

What you are doing is not totally secure.
What will happen if the user tape more than size of your tab ? (Segfault probably).
You really should use something like scanf("%9s", response) (You will have to empty the buffer after it !) :
(Example for tab size = 10) :
query_user(char *response)
{
printf("response after query call before clear=%s\n",response);
strcpy(response,"");
printf("response after clearing before scan=%s\n",response);
printf("Enter another person into the line? y or n\n");
scanf("%9s", response);
clean_buffer();
printf("response after scan=%s\n",response);
printf("scan worked");
}
void clean_buffer()
{
int c;
while ((c = getchar ()) != '\n' && c != EOF);
}
Hope it helps !

First, the code you posted doesn't reproduce the problem. I tested on Linux with Gcc 4.6.2 and on Windows with Visual Studio 2010. In both cases with your exact code my output is:
response=y
When finished with program type "done" to exit
response after while loop and before query call=y
response after query call before clear=y
response after clearing before scan=
Enter another person into the line? y or n
y
response after scan=y
scan workedresponse after while loop and before query call=y
response after query call before clear=y
response after clearing before scan=
Enter another person into the line? y or n
So to better diagnose we need a full working set of code which shows this problem. There are a lot of warnings with the posted code (not sure if those are in your base as well) and sometimes ignoring warnings can get you in a bad place:
main should return int: int main()
Put a return in your main at the end return 0;
query_user needs a void return type: void query_user()
strcpy takes a char * you're giving it a char **
For this last point you can fix it by passing the array to your function such as:
query_user(response); // remove the & operator
And your header for query_user() needs to change such as:
query_user(char response [10]) // remove the * operator
Also note that scanf will leave a '\n' character on stdin, to make sure you don't consume that you can put a single space before the %s:
scanf(" %s", response);
I don't think that any of this will make a big difference, but make sure you make the changes. Please post an update to your code that actually shows the error.

Related

Variable loses its value 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.

:( rejects "" minutes timed out while waiting for input to be rejected" shows when checking my proggram

The program shows the correct infor when I compile it or run it.
The problem is when I check the program. It shows ":( rejects "" minutes
timed out while waiting for input to be rejected" when checking my
proggram. I tried using GetInt and get_intas well. Can you help me,
please?
int main(void)
{
int Minutes,Bottles;
printf("Minutes: ");
scanf("%d", &Minutes);
Bottles = Minutes * 12;
printf("Bottles: %d\n", Bottles);
}
Assuming that you are trying to complete the CS50 problem set named water, you need to include the header file cs50.h and use the GetInt() function in order to pass the checks. If you see the lectures(again), the instructor mentions that this function is written in such a way that it accepts only integer values.
The mistake you make is not accounting for any input other than integer. Use this function like
Minutes = GetInt();
instead of
scanf("%d", &Minutes);

Bus Error on void function return

I'm learning to use libcurl in C. To start, I'm using a randomized list of accession names to search for protein sequence files that may be found hosted here. These follow a set format where the first line is a variable length (but which contains no information I'm trying to query) then a series of capitalized letters with a new line every sixty (60) characters (what I want to pull down, but reformat to eighty (80) characters per line).
I have the call itself in a single function:
//finds and saves the fastas for each protein (assuming on exists)
void pullFasta (proteinEntry *entry, char matchType, FILE *outFile) {
//Local variables
URL_FILE *handle;
char buffer[2] = "", url[32] = "http://www.uniprot.org/uniprot/", sequence[2] = "";
//Build full URL
/*printf ("u:%s\nt:%s\n", url, entry->title); /*This line was used for debugging.*/
strcat (url, entry->title);
strcat (url, ".fasta");
//Open URL
/*printf ("u:%s\n", url); /*This line was used for debugging.*/
handle = url_fopen (url, "r");
//If there is data there
if (handle != NULL) {
//Skip the first line as it's got useless info
do {
url_fread(buffer, 1, 1, handle);
} while (buffer[0] != '\n');
//Grab the fasta data, skipping newline characters
while (!url_feof (handle)) {
url_fread(buffer, 1, 1, handle);
if (buffer[0] != '\n') {
strcat (sequence, buffer);
}
}
//Print it
printFastaEntry (entry->title, sequence, matchType, outFile);
}
url_fclose (handle);
return;
}
With proteinEntry being defined as:
//Entry for fasta formatable data
typedef struct proteinEntry {
char title[7];
struct proteinEntry *next;
} proteinEntry;
And the url_fopen, url_fclose, url_feof, url_read, and URL_FILE code found here, they mimic the file functions for which they are named.
As you can see I've been doing some debugging with the URL generator (uniprot URLs follow the same format for different proteins), I got it working properly and can pull down the data from the site and save it to file in the proper format that I want. I set the read buffer to 1 because I wanted to get a program that was very simplistic but functional (if inelegant) before I start playing with things, so I would have a base to return to as I learned.
I've tested the url_<function> calls and they are giving no errors. So I added incremental printf calls after each line to identify exactly where the bus error is occurring and it is happening at return;.
My understanding of bus errors is that it's a memory access issue wherein I'm trying to get at memory that my program doesn't have control over. My confusion comes from the fact that this is happening at the return of a void function. There's nothing being read, written, or passed to trigger the memory error (as far as I understand it, at least).
Can anyone point me in the right direction to fix my mistake please?
EDIT: As #BLUEPIXY pointed out I had a potential url_fclose (NULL). As #deltheil pointed out I had sequence as a static array. This also made me notice I'm repeating my bad memory allocation for url, so I updated it and it now works. Thanks for your help!
If we look at e.g http://www.uniprot.org/uniprot/Q6GZX1.fasta and skip the first line (as you do) we have:
MNAKYDTDQGVGRMLFLGTIGLAVVVGGLMAYGYYYDGKTPSSGTSFHTASPSFSSRYRY
Which is a 60 characters string.
When you try to read this sequence with:
//Grab the fasta data, skipping newline characters
while (!url_feof (handle)) {
url_fread(buffer, 1, 1, handle);
if (buffer[0] != '\n') {
strcat (sequence, buffer);
}
}
The problem is sequence is not expandable and not large enough (it is a fixed length array of size 2).
So make sure to choose a large enough size to hold any sequence, or implement the ability to expand it on-the-fly.

Console application crashes for unknown reason

I have my piece of code which is shown below
#include<cstdlib>
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
int main()
{
int a;
printf("Please select a choice \n1.Enter New Artist\n2.List All Artist information\n3. Show sorted List of Artists\n4.Add Album to existing Artist\n5.Remove Album from existing Artist\n6.Update Artist info\n7.Search for Artist");
scanf("%d,&a");
if(a==1)
{
printf("no");
}
system("PAUSE");
return EXIT_SUCCESS;
}
On running the code, it displays the menu and if i input 1, it takes a few seconds before it crashes and displays the info
document1.exe has stopped working
How can I debug this problem. I am using dev c++ 4.9.9.2
Your scanf statement is wrong. You are not passing argument (pointer) to it.
Change
scanf("%d,&a");
to
scanf("%d",&a);
For a C solution - I am not certain
aside from previously mentioned
error in scanf formatting (which your compiler should have warned about),
which would have put the result.. well, god knows where on stackā€¦
I'm not certain, but I suspect the compiled code would take the next location in ram as an address, and write there.
Borked stack == really, really, really hard to debug errors.
Since you are using a c++ compiler, if you can use c++, you may wish to consider evaluation of using some of the STL here.
I assume you will be terminating input with a CR
int main (int argv, char** argv]
{
int a;
std::string inputString;
std::cout <<"Please select a choice \n""1.Enter New Artist\n2.List All Artist information\n3. Show sorted List of Artists\n4.Add Album to existing Artist\n5.Remove Album from existing Artist\n6.Update Artist info\n7.Search for Artist";
std::getline(std::cin,inputString);
std::stringstream inputStream(inputString);
inputStream >> a; // could also have been parsed with std::stol, or strtol. - my preference due to error checking - what if your user entered 'byte me'?
if (a==1)
{
printf("no");
}
system("PAUSE");
return EXIT_SUCCESS;
}

fgets() seems to overflow input to other variables

I'm doing a read from a file, but the input seems to "overflow" into other variables.
I have these 2 variables:
char str[250]; //used to store input from stream
char *getmsg; //already points to some other string
The problem is, when I use fgets() to read the input
printf("1TOKEN:%s\n",getmsg);
fp=fopen("m.txt","r");
fp1=fopen("m1.txt","w");
if(fp!=NULL && fp1!=NULL)
printf("2TOKEN:%s\n",getmsg);
while(fgets(str,250,fp)!=NULL){
printf("3TOKEN:%s\n",getmsg);
printf("read:%s",str);
printf("4TOKEN:%s\n",getmsg);
I get something like this:
1TOKEN:c
2TOKEN:c
3TOKEN:b atob atobbody
read:a b atob atobbody
4TOKEN:b atob atobbody
You see how str kind of flows into getmsg. What happened there? How can I avoid this from happening?
Thanks in advance :)
in the code, "getmsg" is called "token", I thought it might have something to do with identical names or something so I changed it to getmsg, same error, so I changed it back...
if(buf[0]=='C'){
int login_error=1;
fp=fopen("r.txt","r");
if(fp!=NULL){
memcpy(&count,&buf[1],2);
pack.boxid=ntohs(count);
memcpy(pack.pword,&buf[3],10);
printf("boxid:%u pword:%s\n",pack.boxid,pack.pword);
while(fgets(str,250,fp)!=NULL){
/*"getmsg"===>*/ token=strtok(str," ");
token=strtok(NULL," ");//receiver uname
token1=strtok(NULL," ");//pword
token2=strtok(NULL," ");//boxid
sscanf(token2,"%hu",&count);//convert char[] to unsigned short
if(pack.boxid==count && strcmp(token1,pack.pword)==0){//uname & pword found
login_error=0;
printf("found:token:%s\n",token);
break;
}
}
if(login_error==1){
count=65535;
pack.boxid=htons(count);
}
if(login_error==0){
count=0;
pack.boxid=htons(count);
}
fclose(fp);
}
printf("1TOKEN:%s\n",token);
if(login_error==0){
int msg_error=1;
fp=fopen("m.txt","r");
fp1=fopen("m1.txt","w");
if(fp!=NULL && fp1!=NULL){
printf("2TOKEN:%s\n",token);
while(fgets(str,250,fp)!=NULL){
printf("3TOKEN:%s\n",token);
printf("read:%s",str);
token1=strtok(str," ");//sender
token2=strtok(NULL," ");//receiver
token3=strtok(NULL," ");//subject
token4=strtok(NULL," ");//body
printf("m.txt:token1:%s token2:%s token3:%s token4:%s\n",token1,token2,token3,token4);
if(msg_error==1 && strcmp(token,token2)==0){//message found
msg_error=0;
count=0;
pack.boxid=htons(count);
strcpy(pack.uname,token1);
strcpy(pack.subject,token3);
strcpy(pack.body,token4);
printf("pack:uname:%s subject:%s body:%s token:%s token2:%s strcmp:%d\n",pack.uname,pack.subject,pack.body,token,token2,strcmp(token,token2));
continue;
}
fprintf(fp1,"%s %s %s %s\n",token1,token2,token3,token4);
}
if(msg_error==1){
count=65534;
pack.boxid=htons(count);
}
printf("count:%u -> boxid:%u\n",count,pack.boxid);
fclose(fp);
fclose(fp1);
}
str[0]='c';
memcpy(&str[1],&pack.boxid,2);
memcpy(&str[3],pack.uname,8);
memcpy(&str[11],pack.subject,20);
memcpy(&str[31],pack.body,200);
str[231]='\0';
bytes=232;
}
}
below is m.txt, it is used to store senders, receivers, subjects and msgbodies:
the naming patter is quite obvious >.^
a b atob atobbody
a c atoc atoccc
b c btoc btoccccc
b a btoa btoaaaaa
So I'm trying to get a msg stored in m.txt for the recipient "c", but it flows over, and by much coincidence, it returns the msg for "b"...
It looks like getmsg is pointing to the third character of your str buffer:
`str` is "a b atob atobbody"
^
|
\__ `getmsg` is pointing there.
Therefore, every time you change str by calling fgets(), the string pointed to by getmsg also changes, since it uses the same memory.

Resources