Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

puts and printf in C

Tags:

c

string

I am new in C. And I found some problem in puts and printf of C.

char str[10];
printf("Input a string.\n");
gets(str);
printf("The string you input is: %s",str);

The output is these if I put more than 10 char

1ang:lab lang$ ./exercise 
Input a string.
warning: this program uses gets(), which is unsafe.
0123456789
Abort trap: 6

But when I add \n at the end of printf, printf("The string you input is: %s\n",str); the output is different.

1ang:lab lang$ ./exercise 
Input a string.
warning: this program uses gets(), which is unsafe.
0123456789
The string you input is: 0123456789
Abort trap: 6

It will first print the string and then occur the error. Could someone explain it?

like image 522
1ang Avatar asked Feb 23 '16 11:02

1ang


3 Answers

You didn't reserve enough space for your string.

Remember that you need an extra element for the null-terminator (\0) that gets added to an array of characters. str[10] is not big enough.

Since the str argument to printf doesn't contain a \0, it overruns the buffer with undefined results.

One way round this is to consider using fgets instead. In its current form, but even reserving enough memory for your test string, you can easily supply a longer one which will again crash your program.

Also, consider appending \n to your printf string: this newline character flushes the output buffer, which will help timely writeback to your console.

like image 138
Bathsheba Avatar answered Oct 02 '22 16:10

Bathsheba


gets is unsafe, in your code, I think it overwrite a part of your stack, maybe the return pointer register (I'am not sure of the name).

Now, why do you have a message in a case, and not in another?

Because printing "\n" in printf will force a flush of what have been bufferized so far.

In first case, the crash occurs before the text have been displayed on your console, but if you use a debugger, will see that it occurs at the same point.

like image 32
Mathieu Avatar answered Oct 02 '22 16:10

Mathieu


Your compiler told you, "warning: this program usesgets(), which is unsafe." but you went ahead anyway. Then you read enough data to overflow your array, presumably corrupting other storage.

What happens next is undefined behaviour, and so anything can happen. In your case, it appears that the printf succeeds, but the corruption causes later code (perhaps the return from the function) to crash. If you flushed stdout (which happens implicitly when you print \n if stdout is a terminal), then you will see the output. If you didn't, the buffered output is lost when the process is destroyed.

like image 28
Toby Speight Avatar answered Oct 02 '22 15:10

Toby Speight