Dynamic fgets in C

Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
6
down vote
favorite
I wanted to make a function that will dynamically retrieve a line from a stream to a buffer. This function just needs to take in the char* and the stream to read from. It'll keep allocating a bigger buffer until it can read all the data into the rtr variable (terminated on new line). Any ways I can improve this would be amazing.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char* dynamic_fgets(char** rtr, FILE* stream)
int bufsize = 1024; //Start at 1024 bytes
char* buf = (char*) malloc(bufsize*sizeof(char));
if(buf == NULL)
perror("Couldn't allocate memory for buf in dynamic_fgetsn");
do
fgets(buf, bufsize, stream);
*rtr = realloc(*rtr, strlen(buf)+strlen(*rtr));
if(*rtr == NULL)
perror("Couldn't allocate memory for *rtr in dynamic_fgetsn");
*rtr = strncat(*rtr, buf, bufsize);
bufsize *= 2;
while(buf[strlen(buf)-1] != 'n');
return *rtr;
int main(int argc, char** argv)
char* buf = (char*) malloc(sizeof(1));
strncpy(buf, "", 1);
printf("Input: ");
dynamic_fgets(&buf, stdin);
printf("Output: %s", buf);
return 0;
c reinventing-the-wheel io
add a comment |Â
up vote
6
down vote
favorite
I wanted to make a function that will dynamically retrieve a line from a stream to a buffer. This function just needs to take in the char* and the stream to read from. It'll keep allocating a bigger buffer until it can read all the data into the rtr variable (terminated on new line). Any ways I can improve this would be amazing.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char* dynamic_fgets(char** rtr, FILE* stream)
int bufsize = 1024; //Start at 1024 bytes
char* buf = (char*) malloc(bufsize*sizeof(char));
if(buf == NULL)
perror("Couldn't allocate memory for buf in dynamic_fgetsn");
do
fgets(buf, bufsize, stream);
*rtr = realloc(*rtr, strlen(buf)+strlen(*rtr));
if(*rtr == NULL)
perror("Couldn't allocate memory for *rtr in dynamic_fgetsn");
*rtr = strncat(*rtr, buf, bufsize);
bufsize *= 2;
while(buf[strlen(buf)-1] != 'n');
return *rtr;
int main(int argc, char** argv)
char* buf = (char*) malloc(sizeof(1));
strncpy(buf, "", 1);
printf("Input: ");
dynamic_fgets(&buf, stdin);
printf("Output: %s", buf);
return 0;
c reinventing-the-wheel io
Perhaps you want getline(3) ?
â Basile Starynkevitch
Aug 26 at 22:57
add a comment |Â
up vote
6
down vote
favorite
up vote
6
down vote
favorite
I wanted to make a function that will dynamically retrieve a line from a stream to a buffer. This function just needs to take in the char* and the stream to read from. It'll keep allocating a bigger buffer until it can read all the data into the rtr variable (terminated on new line). Any ways I can improve this would be amazing.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char* dynamic_fgets(char** rtr, FILE* stream)
int bufsize = 1024; //Start at 1024 bytes
char* buf = (char*) malloc(bufsize*sizeof(char));
if(buf == NULL)
perror("Couldn't allocate memory for buf in dynamic_fgetsn");
do
fgets(buf, bufsize, stream);
*rtr = realloc(*rtr, strlen(buf)+strlen(*rtr));
if(*rtr == NULL)
perror("Couldn't allocate memory for *rtr in dynamic_fgetsn");
*rtr = strncat(*rtr, buf, bufsize);
bufsize *= 2;
while(buf[strlen(buf)-1] != 'n');
return *rtr;
int main(int argc, char** argv)
char* buf = (char*) malloc(sizeof(1));
strncpy(buf, "", 1);
printf("Input: ");
dynamic_fgets(&buf, stdin);
printf("Output: %s", buf);
return 0;
c reinventing-the-wheel io
I wanted to make a function that will dynamically retrieve a line from a stream to a buffer. This function just needs to take in the char* and the stream to read from. It'll keep allocating a bigger buffer until it can read all the data into the rtr variable (terminated on new line). Any ways I can improve this would be amazing.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char* dynamic_fgets(char** rtr, FILE* stream)
int bufsize = 1024; //Start at 1024 bytes
char* buf = (char*) malloc(bufsize*sizeof(char));
if(buf == NULL)
perror("Couldn't allocate memory for buf in dynamic_fgetsn");
do
fgets(buf, bufsize, stream);
*rtr = realloc(*rtr, strlen(buf)+strlen(*rtr));
if(*rtr == NULL)
perror("Couldn't allocate memory for *rtr in dynamic_fgetsn");
*rtr = strncat(*rtr, buf, bufsize);
bufsize *= 2;
while(buf[strlen(buf)-1] != 'n');
return *rtr;
int main(int argc, char** argv)
char* buf = (char*) malloc(sizeof(1));
strncpy(buf, "", 1);
printf("Input: ");
dynamic_fgets(&buf, stdin);
printf("Output: %s", buf);
return 0;
c reinventing-the-wheel io
edited Aug 26 at 18:49
Daniel
4,1232836
4,1232836
asked Aug 26 at 1:09
Axel Persinger
312
312
Perhaps you want getline(3) ?
â Basile Starynkevitch
Aug 26 at 22:57
add a comment |Â
Perhaps you want getline(3) ?
â Basile Starynkevitch
Aug 26 at 22:57
Perhaps you want getline(3) ?
â Basile Starynkevitch
Aug 26 at 22:57
Perhaps you want getline(3) ?
â Basile Starynkevitch
Aug 26 at 22:57
add a comment |Â
5 Answers
5
active
oldest
votes
up vote
10
down vote
Code runs into undefined behavior (UB)
Code fails to test the return value of fgets(). Without knowing the return value is not NULL, strlen(buf) can get called on 1) uninitialized memory or 2) memory in an undefined state or 3) buf from the previous fgets() call.
// UB possible
fgets(buf, bufsize, stream);
*rtr = realloc(*rtr, strlen(buf)+strlen(*rtr));
// Better
if (fgets(buf, bufsize, stream)) {
... strlen(buf) ...
Infinite loop
Should user input end with a non-'n' (think piped input), do loop does not stop before UB kicks in.
Exploitable code
dynamic_fgets(&buf, stdin); allows an external user make the program use excessive resources. There is no upper bound. Defensive coding does not allow memory consumption to go unchecked from potential hostile users or pathological file input.
IMO, dynamic_fgets() , deserves an upper bound parameter. Once exceeded, the routine should not allocative more memory and instead return an error indication.
Code is fooled with ''
How robust do you want your code?
In hostile cases, fgets() may read a null character and fgets() treats it no different than any other non 'n' character. A following strlen(buf) can stop on the usual null character appended by fgets(), yet it will first stop on a read null character. strlen(buf) could be 0 due to such input.
Further this code is then readily exploitable due to buf[strlen(buf)-1] by entering a null character as the first input character. The code is the same as buf[SIZE_MAX] an access outside the allocation and thus UB. At a minimum, do not code buf[strlen(buf)-1] when buf[0] == 0 is possible.
size_t vs. int
Minor: size_t is the right width for array sizing. It is the type return by strlen() and accepted by *alloc(). int can be insufficient for long strings.
2
Code is fooled with ''is an interesting exploit indeed.
â vnp
Aug 26 at 8:04
add a comment |Â
up vote
8
down vote
Make up your mind.
dynamic_fgetsreturns the same information via return value (return *rtr) and the in-out parameter (char ** rtr). Chose one.Do not cast
mallocreturn value. In C it is redundant, and may cause hard-to-find bugs.If, for any reason, you feel you need to cast it, be consistent and cast
reallocas well.Ditto for
sizeof(char). It is 1 by definition; if you still want to spell it out in a call tomalloc, do so forrealloc.*rtr = realloc(*rtr, ....)is dangerous, for it leads to memory leak. Shallreallocfail, the memory pointed by*rtrprior to the call is lost. Consider insteadchar * tmp = realloc(*rtr, ....);
if (tmp == NULL)
// whatever recovery strategy you may come up with, e.g. free(*rtr);
....
return error_indication;
*rtr = tmp;
.... // Business as usualEvery call to
dynamic_fgetsallocates 1024 bytes forbuf, which is neverfreed. 1024 bytes per call leaked.An unconditional reallocation looks strange. Chances are that what
fgetshave read is fitting into an allocated space just fine. Consider testing fornfirst, andrealloconly if necessary.strncat(*rtr, buf, bufsize)must find a terminatingin a memory pointed by*rtr, which leads to quadratic time complexity. You should track where the terminator was placed by the previous iteration.bufis unnecessary. You may read directly into*rtr(plus offset, see the above bullet), thus sparing a copy.
add a comment |Â
up vote
5
down vote
I suggest using the POSIX getline() function as it does what the posted code is trying to do. However, it does take a third parameter (a pointer to a variable to receive the length of the read line). It also returns the number of bytes read (or an EOF indicator).
1
Thanks, I appreciate the suggestion, but I wanted to make something myself so I could understand the language better
â Axel Persinger
Aug 26 at 12:51
1
@AxelPersinger Even if you want to implement something from scratch, it's still a good idea to learn from the design of existing solutions. In particular, the second parameter and the return value differ from yours, and you should consider why.
â 200_success
Aug 26 at 14:51
add a comment |Â
up vote
4
down vote
Bug: buffer overflow
You only ever allocate buf once, with size 1024, here:
int bufsize = 1024; //Start at 1024 bytes
char* buf = (char*) malloc(bufsize*sizeof(char));
But later, you double bufsize on every iteration through the loop, without also doubling the allocation of buf.
Therefore, on the second iteration of the loop, when you run this line:
fgets(buf, bufsize, stream);
you will overflow your buffer, because buf has 1024 bytes, but bufsize will be 2048. As user vnp mentioned, you don't really even need the buf variable if you just read to the end of *rtr and keep track of the number of bytes read so far.
Shlemiel the painter
There is a funny story about a painter who paints slower and slower every day. The punchline:
"I can't help it," says Shlemiel. "Every day I get farther and farther
away from the paint can!"
This story is actually about concatenating strings. In your loop, there are the following operations:
strlen(buf) x2
strlen(*rtr)
strncat(*rtr)
You can't avoid one call to strlen(buf) but the calls involving rtr can be avoided by simply tracking the length of rtr in some variable.
add a comment |Â
up vote
3
down vote
One more thing not mentioned yet. Dont put command line arguments if you dont use them in the code. It is just misleading since you dont use argc and argv. consider to use simply int main (void)
Shouldn't that beint main(void)?
â Thomas Padron-McCarthy
Aug 27 at 8:08
you are right in c++ its without the void but not in c. i will edit it. see google.de/amp/s/www.geeksforgeeks.org/â¦
â Sandro4912
Aug 27 at 9:42
add a comment |Â
5 Answers
5
active
oldest
votes
5 Answers
5
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
10
down vote
Code runs into undefined behavior (UB)
Code fails to test the return value of fgets(). Without knowing the return value is not NULL, strlen(buf) can get called on 1) uninitialized memory or 2) memory in an undefined state or 3) buf from the previous fgets() call.
// UB possible
fgets(buf, bufsize, stream);
*rtr = realloc(*rtr, strlen(buf)+strlen(*rtr));
// Better
if (fgets(buf, bufsize, stream)) {
... strlen(buf) ...
Infinite loop
Should user input end with a non-'n' (think piped input), do loop does not stop before UB kicks in.
Exploitable code
dynamic_fgets(&buf, stdin); allows an external user make the program use excessive resources. There is no upper bound. Defensive coding does not allow memory consumption to go unchecked from potential hostile users or pathological file input.
IMO, dynamic_fgets() , deserves an upper bound parameter. Once exceeded, the routine should not allocative more memory and instead return an error indication.
Code is fooled with ''
How robust do you want your code?
In hostile cases, fgets() may read a null character and fgets() treats it no different than any other non 'n' character. A following strlen(buf) can stop on the usual null character appended by fgets(), yet it will first stop on a read null character. strlen(buf) could be 0 due to such input.
Further this code is then readily exploitable due to buf[strlen(buf)-1] by entering a null character as the first input character. The code is the same as buf[SIZE_MAX] an access outside the allocation and thus UB. At a minimum, do not code buf[strlen(buf)-1] when buf[0] == 0 is possible.
size_t vs. int
Minor: size_t is the right width for array sizing. It is the type return by strlen() and accepted by *alloc(). int can be insufficient for long strings.
2
Code is fooled with ''is an interesting exploit indeed.
â vnp
Aug 26 at 8:04
add a comment |Â
up vote
10
down vote
Code runs into undefined behavior (UB)
Code fails to test the return value of fgets(). Without knowing the return value is not NULL, strlen(buf) can get called on 1) uninitialized memory or 2) memory in an undefined state or 3) buf from the previous fgets() call.
// UB possible
fgets(buf, bufsize, stream);
*rtr = realloc(*rtr, strlen(buf)+strlen(*rtr));
// Better
if (fgets(buf, bufsize, stream)) {
... strlen(buf) ...
Infinite loop
Should user input end with a non-'n' (think piped input), do loop does not stop before UB kicks in.
Exploitable code
dynamic_fgets(&buf, stdin); allows an external user make the program use excessive resources. There is no upper bound. Defensive coding does not allow memory consumption to go unchecked from potential hostile users or pathological file input.
IMO, dynamic_fgets() , deserves an upper bound parameter. Once exceeded, the routine should not allocative more memory and instead return an error indication.
Code is fooled with ''
How robust do you want your code?
In hostile cases, fgets() may read a null character and fgets() treats it no different than any other non 'n' character. A following strlen(buf) can stop on the usual null character appended by fgets(), yet it will first stop on a read null character. strlen(buf) could be 0 due to such input.
Further this code is then readily exploitable due to buf[strlen(buf)-1] by entering a null character as the first input character. The code is the same as buf[SIZE_MAX] an access outside the allocation and thus UB. At a minimum, do not code buf[strlen(buf)-1] when buf[0] == 0 is possible.
size_t vs. int
Minor: size_t is the right width for array sizing. It is the type return by strlen() and accepted by *alloc(). int can be insufficient for long strings.
2
Code is fooled with ''is an interesting exploit indeed.
â vnp
Aug 26 at 8:04
add a comment |Â
up vote
10
down vote
up vote
10
down vote
Code runs into undefined behavior (UB)
Code fails to test the return value of fgets(). Without knowing the return value is not NULL, strlen(buf) can get called on 1) uninitialized memory or 2) memory in an undefined state or 3) buf from the previous fgets() call.
// UB possible
fgets(buf, bufsize, stream);
*rtr = realloc(*rtr, strlen(buf)+strlen(*rtr));
// Better
if (fgets(buf, bufsize, stream)) {
... strlen(buf) ...
Infinite loop
Should user input end with a non-'n' (think piped input), do loop does not stop before UB kicks in.
Exploitable code
dynamic_fgets(&buf, stdin); allows an external user make the program use excessive resources. There is no upper bound. Defensive coding does not allow memory consumption to go unchecked from potential hostile users or pathological file input.
IMO, dynamic_fgets() , deserves an upper bound parameter. Once exceeded, the routine should not allocative more memory and instead return an error indication.
Code is fooled with ''
How robust do you want your code?
In hostile cases, fgets() may read a null character and fgets() treats it no different than any other non 'n' character. A following strlen(buf) can stop on the usual null character appended by fgets(), yet it will first stop on a read null character. strlen(buf) could be 0 due to such input.
Further this code is then readily exploitable due to buf[strlen(buf)-1] by entering a null character as the first input character. The code is the same as buf[SIZE_MAX] an access outside the allocation and thus UB. At a minimum, do not code buf[strlen(buf)-1] when buf[0] == 0 is possible.
size_t vs. int
Minor: size_t is the right width for array sizing. It is the type return by strlen() and accepted by *alloc(). int can be insufficient for long strings.
Code runs into undefined behavior (UB)
Code fails to test the return value of fgets(). Without knowing the return value is not NULL, strlen(buf) can get called on 1) uninitialized memory or 2) memory in an undefined state or 3) buf from the previous fgets() call.
// UB possible
fgets(buf, bufsize, stream);
*rtr = realloc(*rtr, strlen(buf)+strlen(*rtr));
// Better
if (fgets(buf, bufsize, stream)) {
... strlen(buf) ...
Infinite loop
Should user input end with a non-'n' (think piped input), do loop does not stop before UB kicks in.
Exploitable code
dynamic_fgets(&buf, stdin); allows an external user make the program use excessive resources. There is no upper bound. Defensive coding does not allow memory consumption to go unchecked from potential hostile users or pathological file input.
IMO, dynamic_fgets() , deserves an upper bound parameter. Once exceeded, the routine should not allocative more memory and instead return an error indication.
Code is fooled with ''
How robust do you want your code?
In hostile cases, fgets() may read a null character and fgets() treats it no different than any other non 'n' character. A following strlen(buf) can stop on the usual null character appended by fgets(), yet it will first stop on a read null character. strlen(buf) could be 0 due to such input.
Further this code is then readily exploitable due to buf[strlen(buf)-1] by entering a null character as the first input character. The code is the same as buf[SIZE_MAX] an access outside the allocation and thus UB. At a minimum, do not code buf[strlen(buf)-1] when buf[0] == 0 is possible.
size_t vs. int
Minor: size_t is the right width for array sizing. It is the type return by strlen() and accepted by *alloc(). int can be insufficient for long strings.
edited Aug 26 at 8:38
answered Aug 26 at 3:54
chux
11.5k11239
11.5k11239
2
Code is fooled with ''is an interesting exploit indeed.
â vnp
Aug 26 at 8:04
add a comment |Â
2
Code is fooled with ''is an interesting exploit indeed.
â vnp
Aug 26 at 8:04
2
2
Code is fooled with '' is an interesting exploit indeed.â vnp
Aug 26 at 8:04
Code is fooled with '' is an interesting exploit indeed.â vnp
Aug 26 at 8:04
add a comment |Â
up vote
8
down vote
Make up your mind.
dynamic_fgetsreturns the same information via return value (return *rtr) and the in-out parameter (char ** rtr). Chose one.Do not cast
mallocreturn value. In C it is redundant, and may cause hard-to-find bugs.If, for any reason, you feel you need to cast it, be consistent and cast
reallocas well.Ditto for
sizeof(char). It is 1 by definition; if you still want to spell it out in a call tomalloc, do so forrealloc.*rtr = realloc(*rtr, ....)is dangerous, for it leads to memory leak. Shallreallocfail, the memory pointed by*rtrprior to the call is lost. Consider insteadchar * tmp = realloc(*rtr, ....);
if (tmp == NULL)
// whatever recovery strategy you may come up with, e.g. free(*rtr);
....
return error_indication;
*rtr = tmp;
.... // Business as usualEvery call to
dynamic_fgetsallocates 1024 bytes forbuf, which is neverfreed. 1024 bytes per call leaked.An unconditional reallocation looks strange. Chances are that what
fgetshave read is fitting into an allocated space just fine. Consider testing fornfirst, andrealloconly if necessary.strncat(*rtr, buf, bufsize)must find a terminatingin a memory pointed by*rtr, which leads to quadratic time complexity. You should track where the terminator was placed by the previous iteration.bufis unnecessary. You may read directly into*rtr(plus offset, see the above bullet), thus sparing a copy.
add a comment |Â
up vote
8
down vote
Make up your mind.
dynamic_fgetsreturns the same information via return value (return *rtr) and the in-out parameter (char ** rtr). Chose one.Do not cast
mallocreturn value. In C it is redundant, and may cause hard-to-find bugs.If, for any reason, you feel you need to cast it, be consistent and cast
reallocas well.Ditto for
sizeof(char). It is 1 by definition; if you still want to spell it out in a call tomalloc, do so forrealloc.*rtr = realloc(*rtr, ....)is dangerous, for it leads to memory leak. Shallreallocfail, the memory pointed by*rtrprior to the call is lost. Consider insteadchar * tmp = realloc(*rtr, ....);
if (tmp == NULL)
// whatever recovery strategy you may come up with, e.g. free(*rtr);
....
return error_indication;
*rtr = tmp;
.... // Business as usualEvery call to
dynamic_fgetsallocates 1024 bytes forbuf, which is neverfreed. 1024 bytes per call leaked.An unconditional reallocation looks strange. Chances are that what
fgetshave read is fitting into an allocated space just fine. Consider testing fornfirst, andrealloconly if necessary.strncat(*rtr, buf, bufsize)must find a terminatingin a memory pointed by*rtr, which leads to quadratic time complexity. You should track where the terminator was placed by the previous iteration.bufis unnecessary. You may read directly into*rtr(plus offset, see the above bullet), thus sparing a copy.
add a comment |Â
up vote
8
down vote
up vote
8
down vote
Make up your mind.
dynamic_fgetsreturns the same information via return value (return *rtr) and the in-out parameter (char ** rtr). Chose one.Do not cast
mallocreturn value. In C it is redundant, and may cause hard-to-find bugs.If, for any reason, you feel you need to cast it, be consistent and cast
reallocas well.Ditto for
sizeof(char). It is 1 by definition; if you still want to spell it out in a call tomalloc, do so forrealloc.*rtr = realloc(*rtr, ....)is dangerous, for it leads to memory leak. Shallreallocfail, the memory pointed by*rtrprior to the call is lost. Consider insteadchar * tmp = realloc(*rtr, ....);
if (tmp == NULL)
// whatever recovery strategy you may come up with, e.g. free(*rtr);
....
return error_indication;
*rtr = tmp;
.... // Business as usualEvery call to
dynamic_fgetsallocates 1024 bytes forbuf, which is neverfreed. 1024 bytes per call leaked.An unconditional reallocation looks strange. Chances are that what
fgetshave read is fitting into an allocated space just fine. Consider testing fornfirst, andrealloconly if necessary.strncat(*rtr, buf, bufsize)must find a terminatingin a memory pointed by*rtr, which leads to quadratic time complexity. You should track where the terminator was placed by the previous iteration.bufis unnecessary. You may read directly into*rtr(plus offset, see the above bullet), thus sparing a copy.
Make up your mind.
dynamic_fgetsreturns the same information via return value (return *rtr) and the in-out parameter (char ** rtr). Chose one.Do not cast
mallocreturn value. In C it is redundant, and may cause hard-to-find bugs.If, for any reason, you feel you need to cast it, be consistent and cast
reallocas well.Ditto for
sizeof(char). It is 1 by definition; if you still want to spell it out in a call tomalloc, do so forrealloc.*rtr = realloc(*rtr, ....)is dangerous, for it leads to memory leak. Shallreallocfail, the memory pointed by*rtrprior to the call is lost. Consider insteadchar * tmp = realloc(*rtr, ....);
if (tmp == NULL)
// whatever recovery strategy you may come up with, e.g. free(*rtr);
....
return error_indication;
*rtr = tmp;
.... // Business as usualEvery call to
dynamic_fgetsallocates 1024 bytes forbuf, which is neverfreed. 1024 bytes per call leaked.An unconditional reallocation looks strange. Chances are that what
fgetshave read is fitting into an allocated space just fine. Consider testing fornfirst, andrealloconly if necessary.strncat(*rtr, buf, bufsize)must find a terminatingin a memory pointed by*rtr, which leads to quadratic time complexity. You should track where the terminator was placed by the previous iteration.bufis unnecessary. You may read directly into*rtr(plus offset, see the above bullet), thus sparing a copy.
answered Aug 26 at 2:33
vnp
36.8k12992
36.8k12992
add a comment |Â
add a comment |Â
up vote
5
down vote
I suggest using the POSIX getline() function as it does what the posted code is trying to do. However, it does take a third parameter (a pointer to a variable to receive the length of the read line). It also returns the number of bytes read (or an EOF indicator).
1
Thanks, I appreciate the suggestion, but I wanted to make something myself so I could understand the language better
â Axel Persinger
Aug 26 at 12:51
1
@AxelPersinger Even if you want to implement something from scratch, it's still a good idea to learn from the design of existing solutions. In particular, the second parameter and the return value differ from yours, and you should consider why.
â 200_success
Aug 26 at 14:51
add a comment |Â
up vote
5
down vote
I suggest using the POSIX getline() function as it does what the posted code is trying to do. However, it does take a third parameter (a pointer to a variable to receive the length of the read line). It also returns the number of bytes read (or an EOF indicator).
1
Thanks, I appreciate the suggestion, but I wanted to make something myself so I could understand the language better
â Axel Persinger
Aug 26 at 12:51
1
@AxelPersinger Even if you want to implement something from scratch, it's still a good idea to learn from the design of existing solutions. In particular, the second parameter and the return value differ from yours, and you should consider why.
â 200_success
Aug 26 at 14:51
add a comment |Â
up vote
5
down vote
up vote
5
down vote
I suggest using the POSIX getline() function as it does what the posted code is trying to do. However, it does take a third parameter (a pointer to a variable to receive the length of the read line). It also returns the number of bytes read (or an EOF indicator).
I suggest using the POSIX getline() function as it does what the posted code is trying to do. However, it does take a third parameter (a pointer to a variable to receive the length of the read line). It also returns the number of bytes read (or an EOF indicator).
edited Aug 26 at 3:29
200_success
124k14144401
124k14144401
answered Aug 26 at 2:49
user3629249
1,55249
1,55249
1
Thanks, I appreciate the suggestion, but I wanted to make something myself so I could understand the language better
â Axel Persinger
Aug 26 at 12:51
1
@AxelPersinger Even if you want to implement something from scratch, it's still a good idea to learn from the design of existing solutions. In particular, the second parameter and the return value differ from yours, and you should consider why.
â 200_success
Aug 26 at 14:51
add a comment |Â
1
Thanks, I appreciate the suggestion, but I wanted to make something myself so I could understand the language better
â Axel Persinger
Aug 26 at 12:51
1
@AxelPersinger Even if you want to implement something from scratch, it's still a good idea to learn from the design of existing solutions. In particular, the second parameter and the return value differ from yours, and you should consider why.
â 200_success
Aug 26 at 14:51
1
1
Thanks, I appreciate the suggestion, but I wanted to make something myself so I could understand the language better
â Axel Persinger
Aug 26 at 12:51
Thanks, I appreciate the suggestion, but I wanted to make something myself so I could understand the language better
â Axel Persinger
Aug 26 at 12:51
1
1
@AxelPersinger Even if you want to implement something from scratch, it's still a good idea to learn from the design of existing solutions. In particular, the second parameter and the return value differ from yours, and you should consider why.
â 200_success
Aug 26 at 14:51
@AxelPersinger Even if you want to implement something from scratch, it's still a good idea to learn from the design of existing solutions. In particular, the second parameter and the return value differ from yours, and you should consider why.
â 200_success
Aug 26 at 14:51
add a comment |Â
up vote
4
down vote
Bug: buffer overflow
You only ever allocate buf once, with size 1024, here:
int bufsize = 1024; //Start at 1024 bytes
char* buf = (char*) malloc(bufsize*sizeof(char));
But later, you double bufsize on every iteration through the loop, without also doubling the allocation of buf.
Therefore, on the second iteration of the loop, when you run this line:
fgets(buf, bufsize, stream);
you will overflow your buffer, because buf has 1024 bytes, but bufsize will be 2048. As user vnp mentioned, you don't really even need the buf variable if you just read to the end of *rtr and keep track of the number of bytes read so far.
Shlemiel the painter
There is a funny story about a painter who paints slower and slower every day. The punchline:
"I can't help it," says Shlemiel. "Every day I get farther and farther
away from the paint can!"
This story is actually about concatenating strings. In your loop, there are the following operations:
strlen(buf) x2
strlen(*rtr)
strncat(*rtr)
You can't avoid one call to strlen(buf) but the calls involving rtr can be avoided by simply tracking the length of rtr in some variable.
add a comment |Â
up vote
4
down vote
Bug: buffer overflow
You only ever allocate buf once, with size 1024, here:
int bufsize = 1024; //Start at 1024 bytes
char* buf = (char*) malloc(bufsize*sizeof(char));
But later, you double bufsize on every iteration through the loop, without also doubling the allocation of buf.
Therefore, on the second iteration of the loop, when you run this line:
fgets(buf, bufsize, stream);
you will overflow your buffer, because buf has 1024 bytes, but bufsize will be 2048. As user vnp mentioned, you don't really even need the buf variable if you just read to the end of *rtr and keep track of the number of bytes read so far.
Shlemiel the painter
There is a funny story about a painter who paints slower and slower every day. The punchline:
"I can't help it," says Shlemiel. "Every day I get farther and farther
away from the paint can!"
This story is actually about concatenating strings. In your loop, there are the following operations:
strlen(buf) x2
strlen(*rtr)
strncat(*rtr)
You can't avoid one call to strlen(buf) but the calls involving rtr can be avoided by simply tracking the length of rtr in some variable.
add a comment |Â
up vote
4
down vote
up vote
4
down vote
Bug: buffer overflow
You only ever allocate buf once, with size 1024, here:
int bufsize = 1024; //Start at 1024 bytes
char* buf = (char*) malloc(bufsize*sizeof(char));
But later, you double bufsize on every iteration through the loop, without also doubling the allocation of buf.
Therefore, on the second iteration of the loop, when you run this line:
fgets(buf, bufsize, stream);
you will overflow your buffer, because buf has 1024 bytes, but bufsize will be 2048. As user vnp mentioned, you don't really even need the buf variable if you just read to the end of *rtr and keep track of the number of bytes read so far.
Shlemiel the painter
There is a funny story about a painter who paints slower and slower every day. The punchline:
"I can't help it," says Shlemiel. "Every day I get farther and farther
away from the paint can!"
This story is actually about concatenating strings. In your loop, there are the following operations:
strlen(buf) x2
strlen(*rtr)
strncat(*rtr)
You can't avoid one call to strlen(buf) but the calls involving rtr can be avoided by simply tracking the length of rtr in some variable.
Bug: buffer overflow
You only ever allocate buf once, with size 1024, here:
int bufsize = 1024; //Start at 1024 bytes
char* buf = (char*) malloc(bufsize*sizeof(char));
But later, you double bufsize on every iteration through the loop, without also doubling the allocation of buf.
Therefore, on the second iteration of the loop, when you run this line:
fgets(buf, bufsize, stream);
you will overflow your buffer, because buf has 1024 bytes, but bufsize will be 2048. As user vnp mentioned, you don't really even need the buf variable if you just read to the end of *rtr and keep track of the number of bytes read so far.
Shlemiel the painter
There is a funny story about a painter who paints slower and slower every day. The punchline:
"I can't help it," says Shlemiel. "Every day I get farther and farther
away from the paint can!"
This story is actually about concatenating strings. In your loop, there are the following operations:
strlen(buf) x2
strlen(*rtr)
strncat(*rtr)
You can't avoid one call to strlen(buf) but the calls involving rtr can be avoided by simply tracking the length of rtr in some variable.
answered Aug 26 at 23:05
JS1
27k32876
27k32876
add a comment |Â
add a comment |Â
up vote
3
down vote
One more thing not mentioned yet. Dont put command line arguments if you dont use them in the code. It is just misleading since you dont use argc and argv. consider to use simply int main (void)
Shouldn't that beint main(void)?
â Thomas Padron-McCarthy
Aug 27 at 8:08
you are right in c++ its without the void but not in c. i will edit it. see google.de/amp/s/www.geeksforgeeks.org/â¦
â Sandro4912
Aug 27 at 9:42
add a comment |Â
up vote
3
down vote
One more thing not mentioned yet. Dont put command line arguments if you dont use them in the code. It is just misleading since you dont use argc and argv. consider to use simply int main (void)
Shouldn't that beint main(void)?
â Thomas Padron-McCarthy
Aug 27 at 8:08
you are right in c++ its without the void but not in c. i will edit it. see google.de/amp/s/www.geeksforgeeks.org/â¦
â Sandro4912
Aug 27 at 9:42
add a comment |Â
up vote
3
down vote
up vote
3
down vote
One more thing not mentioned yet. Dont put command line arguments if you dont use them in the code. It is just misleading since you dont use argc and argv. consider to use simply int main (void)
One more thing not mentioned yet. Dont put command line arguments if you dont use them in the code. It is just misleading since you dont use argc and argv. consider to use simply int main (void)
edited Aug 27 at 9:42
answered Aug 26 at 21:02
Sandro4912
637120
637120
Shouldn't that beint main(void)?
â Thomas Padron-McCarthy
Aug 27 at 8:08
you are right in c++ its without the void but not in c. i will edit it. see google.de/amp/s/www.geeksforgeeks.org/â¦
â Sandro4912
Aug 27 at 9:42
add a comment |Â
Shouldn't that beint main(void)?
â Thomas Padron-McCarthy
Aug 27 at 8:08
you are right in c++ its without the void but not in c. i will edit it. see google.de/amp/s/www.geeksforgeeks.org/â¦
â Sandro4912
Aug 27 at 9:42
Shouldn't that be
int main(void)?â Thomas Padron-McCarthy
Aug 27 at 8:08
Shouldn't that be
int main(void)?â Thomas Padron-McCarthy
Aug 27 at 8:08
you are right in c++ its without the void but not in c. i will edit it. see google.de/amp/s/www.geeksforgeeks.org/â¦
â Sandro4912
Aug 27 at 9:42
you are right in c++ its without the void but not in c. i will edit it. see google.de/amp/s/www.geeksforgeeks.org/â¦
â Sandro4912
Aug 27 at 9:42
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f202490%2fdynamic-fgets-in-c%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password

Perhaps you want getline(3) ?
â Basile Starynkevitch
Aug 26 at 22:57