fopen() crashing on second use in c [closed] - c

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
for some reason, fopens keeps crashing in my program.
It works once when I am reading the input file and putting the contents into a variable. But for some reason, when I try to make it use fopens again, it crashes...
Could someone please help
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *buf = "\0";
char buffer[99999] ;
int main(int argc, char *argv[])
{
ptr_file =fopen(inputFileLocation,"r");
if (!ptr_file)
{
return 1;
}
while (fgets(buf,maxvalue, ptr_file)!=NULL)
{
strcat(buffer,buf);
}
fclose(ptr_file);
... //workings
//then the program crashes if I add an fopen() and fclose() at the end
}

The accepted answer misses the point. It is not only about buffer overrun.
There is no buffer overrun for maxvalue = 2; yet the program will crash.
But step by step:
fgets(buf, maxvalue, ptr_file) != NULL
The C library function char *fgets(char *str, int n, FILE *stream)
reads a line from the specified stream and stores it into the string
pointed to by str. It stops when either (n-1) characters are read,
the newline character is read, or the end-of-file is reached,
whichever comes first. A null character is automatically appended in
str after the characters read to signal the end of the C string.
In your case buf is string literal of size 2. This is quite likely too small for your needs.
But its not just about the size of buf!
You cannot copy anything to the (constant) string literal! That operation crashes your program with signal 11 even if you read one character.
Constants refer to fixed values that the program may not alter during its execution. These fixed values are also called literals.
What you need is a char array of the proper size.
You could either declare it the same way as char buffer[99999]
// 1.
char buf[SIZE_OF_THE_BUF]; // remember that buf has to accept maxvalue-1 characters + `null` character
or dynamically allocate memory for it in the main()
// 2.a
char *buf;
//
int main()
{
// 2.b
buf = malloc(maxvalue * sizeof(char));
//...
}

You create a pointer named buf that points to space containing a single character '\0'.
Then you use fgets() to try to read an unknown number of characters (you don't show what maxvalue is) into the space pointed to by buf. But that space is only one character long. Reading into it will overrun the space, causing undefined behavior.

Related

Character Array and Null character

#include <stdio.h>
#include <stdlib.h>
int main()
{
int i;
char str[4];
scanf("%s",str);
printf("%s",str);
}
input scan
output scan
Here I declare an array of 4 characters. I used '%s' that is used for strings. I am not able to understand how can we input 4 char elements and get correct answer when one space should be utilized for the NULL character. The input should only work with up to 3 elements.
scanf() does not check its arguments. You could even enter more than 4 characters and scanf() would happily overwrite the memory area that comes after your array. After that, your program might crash or all kinds of funny things might happen. This is called a buffer overflow and it is a common cause of vulnerabilities in software.
as mentioned when you take more than 3 character as input ,and extra chars and \0 will be written outside of array memory(after it) and over write memory which doesn't belong to array.which will cause undefined behavior.
but you can use these to prevent buffer overflow from happening:
scanf("%3s",str);
or
fgets(str, sizeof str, stdin)

Difference between gets() and scanf("%s") [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I declared a character pointer, and used it for to scan a string in runtime; I don't know the number of characters that I'm going to enter, so I didn't use calloc or malloc. The program ends when it reached the line scanf("%s", NewMsg_au8).
I'm using CodeBlocks 17.12 editor.
I tried hard coding one of the input case like, NewMsg_au8="0123456789ABCDEF"; — that works fine.
uint8 * NewMsg_au8;
scanf("%s",NewMsg_au8);//<==
printf("Your entered message is: %s\n",NewMsg_au8);
return NewMsg_au8;
gets(s) and scanf("%s", s) are both unsafe and potentially incorrect because:
with those calls as shown, there is no way for either function to determine the maximum number of characters to store into the array pointed to by s, hence overlong input will cause a buffer overrun leading to undefined behavior.
in your case, it is even worse as s is an uninitialized pointer, so both functions would try a store data into a random address in memory causing undefined behavior in all cases.
gets() cannot be used safely and has been deprecated in and then removed from the C Standard.
However, scanf() can be given a limit with a numeric value between % and s:
#include <stdio.h>
#include <string.h>
char *read_string(void) {
char buf[100];
if (scanf("%99s", buf) == 1) {
printf("Your entered message is: %s\n", buf);
return strdup(buf); /* return an allocated copy of the input string */
} else {
/* no input, probably at end of file */
return NULL;
}
}
Note how only 99 characters can be stored into the array buf to allow for the null byte terminator that marks the end of a C string. The %99s conversion specification lets scanf() store at most 100 bytes into buf, including the '\0' terminator.
That is a typical beginners error. You do not save data in pointers (with gets() or scanf()) but in buffers.
Therefore, you have 2 solutions:
Use an array big enough to hold the data. You have to decide yourself what "big enough" means, according to the details of your application.
Use a pointer, and then allocate memory with malloc() - the size, again, you have to decide it. Do not forget to deallocate the memory when you no longer need it.
I tried hard coding one of the input case like, NewMsg_au8="0123456789ABCDEF"; — that works fine.
That is normal, because in that case the compiler automatically allocates enough memory to hold the string.
Please always remember when working with strings: you always need to allocate an extra byte for the terminating null character - the mark of the end of the string. Otherwise, you will need to ask questions again :)

fprintf gives unexpected output while sending it to file [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char name[50];
int main()
{
FILE *fp;
fp = fopen("./account.txt","a+");
memset(name,'-',50);
scanf("%s",name);
printf("%s",name); // i get correctoutput
fprintf(fp,"%s",name); // I get wrong output
return 0;
}
In my code I have
-- global declaration
char name[50];
and in main I use
memset(name,'-',49);
and read the value into the string using scanf. I am getting two different output's
//assume I give the input as test
If I use printf to print the char array onto the monitor I get proper output as test
If i use fprintf and print the char array onto file I get wrong output,
like first 49 characters as '-' followed by a 0 then whatever I type (In this case test)
-------------------------------------------------0test
Can someone explain what's happening ? Or how to tackle such problems ?
char name[50];
...
int main()
{
memset(name, '-', 50);
}
Strings in C are characters which are contiguous in memory, followed by a NULL character ('\0') to mark the end of the string. When printing a string, printf will print each character in the string until it encounters the NULL byte, then stop.
In this case, the whole string starts off as NULL characters (because it's an un-initialised global), then you overwrite all of the string with '-'. By doing so, there is no longer a NULL terminator to mark the end of the string.
We're now into the land of undefined behaviour. The printf call worked because it just so happened that the next bit of storage was a zero in that case, but such behaviour must not be relied upon (again...undefined behaviour).
To fix this, you need to add the null terminator manually, for example:
char name[50];
int main()
{
memset(name, '-', 49); // Note we're not writing to the last byte now!
name[49] = '\0';
}

Inputting an arithmatic statement in c and return the value [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
(I am very bad at inputting/processing strings in C. Hope this question will teach me a lot.)
I am trying to make a function that will input an arithmatic string from stdin, e.g 23 + 45 * 6 - 5, and return the value.
There are multiple strings, entered one after another, and can be of any length and the operator precedence doesn't matter, i.e., it processes string sequentially.
The problems that I faced are :-
\n from previous string is also considered a string.So if I input 3 strings , it will actually be 6, 3 strings and 3 \n.
I used a char pointer and used char * input; scanf(" %s",input);, but in addition to above problem, I also get segmentation fault, which I guess is due to missing \0.
My question is forget what mess I did, what would you have done or what's the best way to handle string input in the above scenario. A dummy code is sufficient.Thanks.
What I was doing
#include <stdio.h>
int main()
{
int t; //no of test cases
char input;
scanf("%d",&t);
while(t--)
{
while((input=getchar())!='\n')
{
//use switch to identify char and follow appropriate action
printf("%c\n",input );
}
}
return 0;
}
As suggested by Joachim Pileborg, use fgets. Use a char array, instead of one char variable, to store the string.
char input[100];
fgets(input, sizeof(input), stdin);
The advantage of fgets over sscanf is that fgets can read spaces in your input.
It will include the end-of-line byte \n, so 3 strings will not turn into 6 strings.
As usual with fgets, there is an arbitrary limit on the length of the input. If the user inputs something longer than 98 bytes, the system cannot fit it all (plus end-of-line \n and end-of-string \0 bytes), and the program will receive truncated string.
If you cannot tolerate that, use getline (it's harder to use, so use fgets if in doubt).
After you scan your string in, check to see if it is a '\n', if it is just ignore processing it and move to the next one.
Or you could try:
char input[101];
scanf("%s\n", &input);
First of all. Your idea of writing an fomular expression analyzer as a first projekt is not a very good one. Start with a simpler project.
You get the sagmentation fault, because you try to read data (with the scanf()) into a not initialized pointer.
char *input;
will not allocate any memory for the string you want to read with scanf(). You have to use a buffer something like
char input[256];
and give the pointer to the buffer to scanf("%s",input) (oder for better understanding scanf("%s",&input[0]);
Anywhere, this buffer has only 255 chars to store and you must be aware, that if you enter more then 255 chars in the scanf() you will get an illegal memory access as well.
Claus

Arrays Stack Overflow [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
#include
int main(void)
{
char str[100]="88888888888888";
char t[20]="";
gets(t);
puts(str);
puts(t);
return 0;
}
The first line
555555555555555555555555555555555
is put in.
Why str is 55555555555? Why str isn't 88888888888888888 or 55555555555588888?
You overriden the t buffer, and reached the str buffer, where the rest of the input, and the null terminator was set. And puts prints only until the null terminator.
Pretty much looks like that:
[ t (20) ][str(100) ]
55555555555555555555 5555555555555\0
Note that although t is declared as char[20], when you print it you get the full input (longer than 20), since puts stops at the null terminator (again).
BTW, this is a buffer overflow, not a stackoverflow, but stack overflow is possible on this codeas well.
As Binyamin said it is caused by the overflow you trigger because of the input string being too long. However it is a bit random thing - sometimes the two memory allocations will happen just next to each other and the string will extend to the neighbouring variables, sometimes it might not happen.
I advise you to place guard conditions for such kind of overflows.
If you see in the gets documentation:
Notice that gets does not behave exactly as fgets does with stdin as
argument: First, the ending newline character is not included with
gets while with fgets it is. And second, gets does not let you specify
a limit on how many characters are to be read, so you must be careful
with the size of the array pointed by str to avoid buffer overflows.
In your case if you do not know the size apriory maybe it is better idea to use fgets as it is more secure (though a bit slower).
When you enter a string of more than 20 5s, it overruns the buffer that was allocated to t and extends into the buffer that was allocated to str.
Then it displays the contents of str, which is the string you entered, starting at the 21st character.
Finally, it displays the contents of t, but since that string doesn't end with a null character, it continues displaying memory (which is the buffer assiged to str) until it encounters the null character after all the 5s.
In order to avoid those allocation overlapping issues you can try this alternative, so that the allocation takes place at runtime if I'm not wrong:
#include <iostream>
int main(void)
{
char *str;
char *t;
str = new char(100);
str = (char*)"88888888888888";
t = new char(20);
std::cin >> t;
puts(str);
puts(t);
return 0;
}

Resources