views:

606

answers:

7

Why does the following have the effect it does - it prints a terminal full of random characters and then exits leaving a command prompt that produces garbage when you type in it. (I tried it because I thought it would produce a seg fault).

http://s4.tinypic.com/r9qxbt.jpg

#include <stdio.h>

int main(){
    char* s = "lololololololol";
    while(1){
     printf("%c", *s);
     s++;
    }
}

it was compiled with:

gcc -std=c99 hello.c
+7  A: 

You are just printing out what is in memory because your loop doesn't stop at the end of the string. Each random byte is interpreted as a character. It will seg fault when you reach the end of the memory page (and get into unreadable territory).

Lou Franco
+7  A: 

Because you have an infinite loop (while(1)), and you keep getting the current value of pointer (*s), and then moving the pointer one char forward (s++). This has the effect of marching well past the end of the string into "garbage" (uninitialized memory), which gets printed to the console as a result.

mipadi
+20  A: 

It will eventually seg fault, but before that it'll print out whatever bytes are in the same page. That's why you see random chars on the screen.

Those may well include escape sequences to change (say) the character encoding of the console. That's why you end up with gibberish when you type on the console after it's exited, too.

Jon Skeet
It's probably also why he thinks its exiting rather than segfaulting - the "Segmentation fault" message itself is also transformed into gibberish.
Adam Bellaire
+7  A: 

In addition to what everyone else said in regards to you ignoring the string terminal character and just printing willy-nilly what's in memory past the string, the reason why your command prompt is also "garbage" is that by printing a particular "unprintable" character, your terminal session was left in a strange character mode. (I don't know which character it is or what mode change it does, but maybe someone else can pipe in about it that knows better than I.)

Jim Buck
It all depends on what terminal emulation he's using, of course. Xterm defaults to DEC VT-220 mode, I think. Here's a partial list of terminal control codes for that mode: http://www.connectrf.com/Documents/vt220.html lists
Mark Bessey
+2  A: 

Expanding ever so slightly on the answers given here (which are all excellent) ... I ran into this more than once myself when I was just beginning with C, and it's an easy mistake to make.

A quick tweak to your while loop will fix it. Everyone else has given you the why, I'll hook you up with the how:

#include <stdio.h>

int main() {
    char *s = "lolololololololol";
    while (*s != '\0') {
        printf("%c", *s);
        s++;
    }
}

Note that instead of an infinite loop (while(1)), we're doing a loop check to ensure that the pointer we're pulling isn't the null-terminator for the string, thus avoiding the overrun you're encountering.

If you're stuck absolutely needing while(1) (for example, if this is homework and the instructor wants you to use it), use the break keyword to exit the loop. The following code smells, at least to me, but it works:

#include <stdio.h>

int main() {
    char *s = "lolololololololol";
    while (1) {
        if (*s == '\0')
            break;
        printf("%c", *s);
        s++;
    }
}

Both produce the same console output, with no line break at the end:

lolololololololol

John Rudy
+1  A: 

Your loop doesn't terminate, so println prints whatever is in the memory after the text you write; eventually it will access memory it is not allowed to read, causing it to segfault.

You can change the loop as the others suggested, or you can take advantage of fact that in c, zero is false and null (which terminates all strings) is also zero, so you can construct the loop as:

while (*s) {

Rather than:

while (*s != '\0')

The first one may be more difficult to understand, but it does have the advantage of brevity so it is often used to save a bit of typing.

tomjen
A: 

Also, you can usually get back to your command prompt by using the 'reset' command, typing blindly of course. (type Enter, reset, Enter)