Bus Error on void function return - c

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.

Related

Recursive function : abort-condition

We need to create a binary tree which contains content of textfiles. The pointer selection_a and selection_b pointing to another textfile in the directory.
The structure of the textfiles is following:
line: Title
line: OptionA
line: OptionB
line: Text.
The first file is given as parameter while starting the program. All files should be saved at the beginning of the program. Then the text of the first file shows, and the user can input A or B to continue. Based on the selection, the text of File Option A/B is shown and the user can decide again.
The last file of a tree contains no Options: lines 2 and 3 are "-\n".
The problem is, this code only reads all the option A files of the first tree. It doesn't read in any B-Options. In the end, the program shows a memory access error.
I think the problem is that the readingRows function has no abort condition.
current->selection_a = readingRows(input_selection_a);
current->selection_b = readingRows(input_selection_b);
I know the code may be kind of chaotic, but we are beginners in programming. Hope anybody can help us to write an abort-condition.
The function should be aborted if the content of option A (line 3) is "-\n".
Here is the whole function:
struct story_file* readingRows(FILE *current_file)
{
char *buffer = fileSize(current_file);
char *delimiter = "\n";
char *lines = strtok(buffer, delimiter);
int line_counter = 0;
struct story_file *current = malloc(sizeof(struct story_file));
while(lines != NULL)
{
if(line_counter == 0)
{
current->title = lines;
}
else if(line_counter == 1)
{
char *filename_chapter_a = lines;
FILE *input_selection_a = fopen(filename_chapter_a, "r");
if(input_selection_a)
{
current->selection_a = readingRows(input_selection_a);
}
fclose(input_selection_a);
}
else if(line_counter == 2)
{
char *filename_chapter_b = lines;
FILE *input_selection_b = fopen(filename_chapter_b, "r");
if(input_selection_b)
{
current->selection_b = readingRows(input_selection_b);
}
fclose(input_selection_b);
}
else if (line_counter >= 3)
{
current->text = lines;
}
lines = strtok(NULL, delimiter);
line_counter++;
}
return current;
}
There are two items that define a terminating recursive function:
One or more base cases
Recursive calls that move toward a base case
Your code has one base case: while (lines!=NULL) {} return current;, it breaks the while loop when lines is NULL and returns current. In other words, within any particular call to your function, it only terminates when it reaches the end of a file.
Your code moves toward that base case as long as your files do not refer to each other in a loop. We know this because you always read a line, take an action according to your if-else block, and the read the next line. So you always move toward the end of each file you read.
But as you note, the issue is that you don't have a case to handle "no Options", being when lines 2 or 3 are "-\n". So right now, even though you move through files, you are always opening files in line 2. Unless a file is malformed and does not contain a line 2, your recursive call tree never ends. So you just need to add another base case that looks at whether the beginning of lines matches "-\n", and if it does, return before the recursive call. This will end that branch of your recursive tree.
Inside of your while loop, you will need code along the lines of:
if `line_counter` is `2` or `3`
if `lines` starts with your terminating sequence "-\n"
return current
else
`fopen` and make the recursive call
In the parent function that made the recursive call, it will move to the next line and continue as expected.
P.S. Make sure you use free for each malloc you do.

C Curl 400 Bad Request keyword "on"

I wrote a C Program that calls a webservice with cURL. I started my test by hardcoding the address of the webservice with parameters like this :
http://....php?type=adresse&texte=XYZ
It worked fine so I've tried to concatenate a variable for field texte has shown below but it failed and returned me 400 Bad Request.
We checked the content of the request and there is a keyword "on" in front of the webservice address and I don't know where that come from.
on http://....php?type=adresse&texte=xyz&indDebut=0&indFin=1&epsg=900913&format=json"
char* mystrcat( char* dest, char* src )
{
while (*dest) dest++;
while (*dest++ = *src++);
return --dest;
}
recherche = "G0A3B0";
pcbak_adresse(recherche);
const char * pcbak_adresse(const char *details)
{
...
char * lien;
const char * fin_lien;
lien = "http://....php?type=adresse&texte=";
fin_lien = "&indDebut=0&indFin=1&epsg=900913&format=json";
/*Concatenation function*/
mystrcat(details, fin_lien);
mystrcat(lien, details);
/* Set CURL parameters */
curl_easy_setopt(curlHandler, CURLOPT_URL, lien);
curl_easy_setopt(curlHandler, CURLOPT_CUSTOMREQUEST, "GET");
curl_easy_setopt(curlHandler, CURLOPT_WRITEFUNCTION, callback_func);
curl_easy_setopt(curlHandler, CURLOPT_WRITEDATA, &str);
res = curl_easy_perform(curlHandler);
/* Check for errors */
if (res != CURLE_OK)
return curl_easy_strerror(res);
...
}
Thanks for your help!
No matter what mystrcat() is,
mystrcat(lien, details);
is wrong.
If it creates a new string composed by the two inputs, it's not being captured anywhere.
If it tries to write to lien it's undefined behavior. Because you cannot modify string literals which is what lien is.
The same reasoning probably applies to details, but you didn't post details declaration and/or definition.
Do not use anything like strcat() except if you want to do it only once.
To concatenate strings use something like a structure where you store the length of the current string, the size of the target array, and of course the target array. You can then resize the target when you need to, you don't need to find the end of the target string every time (which is what strcat() will do), you also have the advantage of controlling how you append to the string with a lot of detail.
To achieve what you want, you can do this
char lien[256];
int length;
length = snprintf(
lien,
sizeof(lien),
"http://....php?type=adresse&texte=%s&indDebut=0&indFin=1&epsg=900913&format=json",
details
);
if ((length >= sizeof(lien)) || (length == -1))
return error_occurred_here();
Also, returning a static string (which probably is what curl_easy_strerror() returns), and a tentatively dynamic one from the same function is bad design, because,
You can't tell whether it's an error or the JSON returned from the link.
You will need some method to determine whether it's a static string or the one generated in the function in order to free() it.

What can be used to replace the if statement in this bit of code written in C?

The following is my attempt to scan a file to search and see if an entered username is taken already. The code doesn't work because of the if statement.
for (x = 0; x < 100; x++) {
/* for loop allows the user to keep entering usernames until they come up with an unused username. */
FILE *userlist; /*The userlist file holds all the taken usernames */
userlist = fopen("userlist.txt", "r");
fseek(userlist, x, SEEK_SET); /* This starts the search at the place x, which is incremented each time. */
fscanf(userlist, " %s", &username_ext); /* This scans the file contents after x and stores it in the username_ext variable */
if (strcmp(username, username_ext) == 0) { /* If the username entered and the strings after the x are the same, the loop terminates. */
printf("\nThe username is already taken.");
break;
}
fclose(userlist);
}
The code will never work, especially if each entry in the file is of variable length.
Instead you should open the file before the loop, skip the seeking (which will almost never work in a text file, and especially not the way you show it being used). Then you can read a string (using either fgets or fscanf) and compare to the username given.
Something like the following pseudo-ish code:
file = open_file()
while (fscanf("%s", username_ext) == 1)
{
if (strcmp(username, username_ext) == 0)
{
// Username found
}
}
To explain why the code, as shown in the question, will never work, the fseek call will set the position to the offset x in the file from the start. And that offset is in bytes, not in "records" or "elements".
And if the input file is a text file where each record is of different length, there is simply no way of seeking to a specific record without knowing its position beforehand.

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.

Why does my program read an extra structure?

I'm making a small console-based rpg, to brush up on my programming skills.
I am using structures to store character data. Things like their HP, Strength, perhaps Inventory down the road. One of the key things I need to be able to do is load and save characters. Which means reading and saving structures.
Right now I'm just saving and loading a structure with first name and last name, and attempting to read it properly.
Here is my code for creating a character:
void createCharacter()
{
char namebuf[20];
printf("First Name:");
if (NULL != fgets(namebuf, 20, stdin))
{
char *nlptr = strchr(namebuf, '\n');
if (nlptr) *nlptr = '\0';
}
strcpy(party[nMember].fname,namebuf);
printf("Last Name:");
if (NULL != fgets(namebuf, 20, stdin))
{
char *nlptr = strchr(namebuf, '\n');
if (nlptr) *nlptr = '\0';
}
strcpy(party[nMember].lname,namebuf);
/*Character created, now save */
saveCharacter(party[nMember]);
printf("\n\n");
loadCharacter();
}
And here is the saveCharacter function:
void saveCharacter(character party)
{
FILE *fp;
fp = fopen("data","a");
fwrite(&party,sizeof(party),1,fp);
fclose(fp);
}
and the loadCharacter function
void loadCharacter()
{
FILE *fp;
character tempParty[50];
int loop = 0;
int count = 1;
int read = 2;
fp= fopen("data","r");
while(read != 0)
{
read=fread(&tempParty[loop],sizeof(tempParty[loop]),1,fp);
printf("%d. %s %s\n",count,tempParty[loop].fname,tempParty[loop].lname);
loop++;
count++;
}
fclose(fp);
}
So the expected result of the program is that I input a name and last name such as 'John Doe', and it gets appended to the data file. Then it is read in, maybe something like
1. Jane Doe
2. John Doe
and the program ends.
However, my output seems to add one more blank structure to the end.
1. Jane Doe
2. John Doe
3.
I'd like to know why this is. Keep in mind I'm reading the file until fread returns a 0 to signify it's hit the EOF.
Thanks :)
Change your loop:
while( fread(&tempParty[loop],sizeof(tempParty[loop]),1,fp) )
{
// other stuff
}
Whenever you write file reading code ask yourself this question - "what happens if I read an empty file?"
You have an algorithmic problem in your loop, change it to:
read=fread(&tempParty[loop],sizeof(tempParty[loop]),1,fp);
while(read != 0)
{
//read=fread(&tempParty[loop],sizeof(tempParty[loop]),1,fp);
printf("%d. %s %s\n",count,tempParty[loop].fname,tempParty[loop].lname);
loop++;
count++;
read=fread(&tempParty[loop],sizeof(tempParty[loop]),1,fp);
}
There are ways to ged rid of the double fread but first get it working and make sure you understand the flow.
Here:
read=fread(&tempParty[loop],sizeof(tempParty[loop]),1,fp);
printf("%d. %s %s\n",count,tempParty[loop].fname,tempParty[loop].lname);
You are not checking whether the read was successful (the return value of fread()).
while( 1==fread(&tempParty[loop],sizeof*tempParty,1,fp) )
{
/* do anything */
}
is the correct way.
use fopen("data","rb")
instead of fopen("data","r") which is equivalent to fopen("data","rt")
You've got the answer to your immediate question but it's worth pointing out that blindly writing and reading whole structures is not a good plan.
Structure layouts can and do change depending on the compiler you use, the version of that compiler and even with the exact compiler flags used. Any change here will break your ability to read files saved with a different version.
If you have ambitions of supporting multiple platforms issues like endianness also come into play.
And then there's what happens if you add elements to your structure in later versions ...
For robustness you need to think about defining your file format independently of your code and having your save and load functions handle serialising and de-serialising to and from this format.

Resources