1ang
1ang

Reputation: 321

puts and printf in C

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?

Upvotes: 5

Views: 535

Answers (4)

Toby Speight
Toby Speight

Reputation: 30809

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.

Upvotes: 1

muXXmit2X
muXXmit2X

Reputation: 2765

What you have there is a great example of undefined behavior. It is not definied what happens if you exceed the bufferd size of an array. As others have pointed out you realy should not use gets. The function is not considered deprecated for no reason. Better use fgets or fscanf.

I would also recommend you to write a "safe" input function using the return value of scanf. Or you could use a combination of fgets and sscanf to read whole lines from the input and manipulate the read string afterwards using sscanf as in this answer.

Upvotes: 0

Bathsheba
Bathsheba

Reputation: 234695

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.

Upvotes: 7

Mathieu
Mathieu

Reputation: 9629

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.

Upvotes: 2

Related Questions