tags:

views:

1102

answers:

21

Hi

I have often heard that C can crash spectacularly. Recently I got my first taste of this when a function I expected to return a string instead returned little happy faces. Since then I have been being more careful with initializing pointers and mallocing memory for arrays. Still, though, I have trouble believing that a program could crash THAT badly...

I guess it would depend on the scope of the program though? I mean, if a bug in a program that dealt with your fan copied happy faces into some important space in memory...?

My question is, how much myth is there in the world of spectacular C crashes? Can I get some concrete examples of dangerous things that one ought to avoid?

z.

+16  A: 

I think it was probably worse way back in the pre-virtual memory days when you could trash other processes memory, but nowadays the worst that can happen is really just crashing your own program. Usually via segmentation faults from bad pointers.

That excludes of course blowing things up by misusing system resources - you can do that in any language.

Eric Petroelje
+10  A: 

The worst thing that happened to me were memory corruptions which did not cause a crash immediately, but after a while.. making it so hard to detect.. argh

seq
I became paranoid about abusing assert for a while because of scenario's like yours, where a tiny little mistake slowly leaks memory or worse corrupts data silently over a duration of time.
David
+4  A: 

Well, if you're writing kernel code, sometimes you can overwrite system critical bits of memory, such as interrupt vectors, global descriptor tables, process tables, causing all sorts of fun stuff!

samoz
+19  A: 
Tom Ritter
+1  A: 

If your code is running on a remotely modern OS, you can't copy happy faces into random points in memory. You can crash as much as you want, and it will just result in the termination of your process.

The closest you can come to actually messing up your system is abusing processor/memory/disk resources, or spawning so many subprocesses that the OS runs out of PIDs (if it's still using a 32-bit value to store those).

DNS
Considering the operating system must allocate a stack for each process and enough space in memory for the process itself, I'd imagine you'd run out of memory before the OS will run out of PIDs.
dreamlax
+2  A: 

Nowadays is kind of hard making C crash that hard (unless you are coding an OS Kernel or something like that).

Back in the DOS/Win95/Win98 days, you could make a C program chash really, really badly. I used to get this a lot:

Whenever I had a dangerous pointer operation which messed with the memory, I got a character based screen full of all sorts of characters, in different colors, some of them, blinking!!! I guess the operations messed someway with Video Memory.

But today, since processes run within safe kernels, the worst you'll get if your process going away.

Pablo Santa Cruz
+4  A: 

C itself can't crash anything. Sloppy programming can crash everything.

The "happy faces" are an indication that your code corrupted memory. The only thing C had to do with that is the fact that you chose to use it. (And the fact your OS allowed it to happen is surprising - are you still running a version of DOS?)

Ken White
Eh, you can still scribble over memory as long as it is yours :P You can also read past memory pointers, once again, as long as it is yours! So you don't need to run DOS just to get smiley faces to show up!
X-Istence
Point taken. I guess it's been so long since I did that I wouldn't have thought it was still possible. <g> Last time it happened to me, IIRC it was DOS 3.2, and I got happy and sad faces and blinking colors. :-) Quite attractive, actually.
Ken White
however, I am not using windows to run my programs, only to compile them. I am using the Nintendo DS to run them, so I aught to be more careful!
Ziggy
Yes, you ought to be much more careful. :-)
Ken White
The smiling faces happens when you mistakenly assign a bool value to a char. while ((char c = cin.get()) != 'q') can lead to that.
Lucas Cardoso
+10  A: 

Back when I was learning to program C++, it was on a Mac running system 7 or 8 I don't remember which. Anyway, it had no protected virtual memory so a lot of mistakes like leaving a dangling pointer or a buffer overrun would cause the whole computer to crash. I recall that when Apple first announced they were going to create a new OS which had protected memory space at Macworld or something, they showed the source code for a program:

while (true)
  *(int *)i++ = 1;

And when they ran the program and just the program terminated, and not the whole machine (it had a message like "You do not need to restart your computer") the whole room full of developers apparantly burst into applause. Anyway, obviously not having protected memory really made programming C or C++ really tough because of the increased severity of the crash.

Nowadays it is not such a big deal unless you are programming something that runs at supervisor level, you do not have the ability to crash the OS.

1800 INFORMATION
I wrote a program similiar to that one on my C-64. It was "snake". The snake duly went across the first row, wrapped across the second row, etc, and off the bottom of the screen into whatever memory followed drawing little snakes and leaving behind spaces. Eventually it ate it's own code. Crash.
WW
Lol I did something incredibly similar with my c-64
Erik Forbes
Those stories are awesome! My first big confusing error was a stack overflow caused by instantiating mouse listeners inside a while loop. While loops!
Ziggy
+1  A: 

There was a computer, the Commodore PET 4032 (aka the "Fat 40") where it was actually possible to permanently burn out the video chip if you poked the wrong value into the wrong part of memory. You can imagine that if there had been a C compiler on that machine, a wild pointer could actually do irreparable physical damage to the computer.

Paul Tomblin
+5  A: 

The operating system prevents most horrible issues these days. The worst I've ever done is hard-lock the machine (just had to reboot by holding down the power button) and scramble a few files.

All depends what resources you're accessing, really. If you're writing files, there are some ways directory structures can get tangled that used to confuse system utilities, but most of those problems have been fixed. If you're doing something as root, well, then you can sure make a mess because many more system files are writeable. If you're using the network, there's a lot of stuff that can go moderately wrong, but not much more than using up too much bandwidth is likely. Of course, a few years of programming and you'll see all sorts of unlikely things.

For the most part though, it's ok to experiment and play around. These days the systems are resilient enough that you won't make a mess that's too hard to get back out of. The operating system keeps each program to its own piece of memory, and disallows access to change critical systems unless you're administrator/root. Your garden variety dangling pointer may print funny things or crash your program, but it isn't going to destroy a modern computer.

From a comment in another reply: "I am using the Nintendo DS to run them"

Ok, that matters! (First: Awesome idea! Sounds like fun.) Coding for something like that is not the same in terms of what can go wrong as most coding for a desktop computer. A brief look at the documentation for libnds and some tutorials on Nintendo DS programming indicates to me that there's no OS to speak of. So, I have no idea how much you could do with a stray pointer, probably a lot. Possibly something damaging. It might be a good idea to hunt for people who've done programming for that platform before, see what they have to say.

Kim Reece
Hmm yeah! I've been running my program on a DS emulator, but am scared to death to try it on my DS. I wish the libnds guys read Stackoverflow.
Ziggy
+5  A: 

Here is a quick snippet from Henry Spencer's "Ten Commandments for C Programmers":

  • Commandment #2 - Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.
  • Clearly the holy scriptures were mis-transcribed here, as the words should have been ``null pointer'', to minimize confusion between the concept of null pointers and the macro NULL (of which more anon). Otherwise, the meaning is plain. A null pointer points to regions filled with dragons, demons, core dumps, and numberless other foul creatures, all of which delight in frolicing in thy program if thou disturb their sleep. A null pointer doth not point to a 0 of any type, despite some blasphemous old code which impiously assumes this.

For those who are not familiar with C, I think the best written concise introduction to C is done by "The Ten Commandments for C Programmers (Annotated Edition)" by Henry Spencer. The way it is written really gets across to the reader the dangers of C ... while at the same time being funny ( which means the reader will actually pay attention more ).

=========================

Personally... C doesn't crash that badly when you are doing desktop development because you have the luxury of seg-faulting. Seg-faults are when the OS sees you trying to REALLY F' things up and it says "hey! you aren't allowed there" and stops the process.

When you are doing embedded C development... that is when you get the REALLY spectacular crazy stuff... i.e. they REQUIRE you to power-cycle 99.9% of the time. Like this one time where the code somehow messes up my call stack... and then you are executing some random other function... and then the ISR somehow is still going... and it takes 2 weeks to fix that kind o bug.

Trevor Boyd Smith
A: 

Well, back in the DOS days, I managed to over-write part of the boot sector - nothing like rebooting to find "OS Not Found" or whatever the message was.

You learn the hard way to be very, very careful writing to disk after that...

chris
+1  A: 

Back in the DOS days I actually over-wrote bios information. Had to get a tech to fix it. My first home computer - 286. Unbootable after a day or two.

Tom
A: 

C lets you deal with the machine pretty close to directly. How spectacularly it can crash is a function of what the machine can do.

So: A user mode process without special privileges in a nice modern operating system won't really do that much. But you have software all over the place. Think about the software controlling the braking systems in a train. Think about the software running the emergency intercom when someone really needs help. Think about the software running the signs on a busy highway. Think about the software running a guided missile system.

There is software all over the place these days. A lot of it is written in C.

janm
+1  A: 

how bad do you want it to crash?

A: 

Back when I was writing the Win98 drivers, the BSOD haunted everyone. I remember the following mistake I made

typedef struct _SOME_TAG_ {

    int nSomeVar;
    int nSomeMore;
    ...

} MYSTRUCT, *PMYSTRUCT;

.... PMYSTRUCT pMyStruct;

// And I use this structure without allocating any memory ;-) pMyStruct->nSomeVar = 0;

And the driver crashes were so horrible but we had a SoftICE from Numega, Though it is only 10 years ago .. I feel its like ages back

Alphaneo
+1  A: 

On any OS with protected memory the worst that can happen is that your process crashes. Now if your process happens to be part of the kernel or a kernel extension then you can obviously crash the whole OS but that is the worst you can do.

However, really this the same with many other languages (for example in C deference a null pointer, in java use an object reference set to null, both will crash your process).

So, I believe with protected memory, C can't do any more damage than any other Language (unless your process is part of the OS ;))

hhafez
I would bet the worst that can happen is actually with drivers ;)
eglasius
+1  A: 

prior to protected-memory architectures, most of the jump vectors used by the operating system were stored in the zero page of memory (addresses starting at zero)

so writing to memory locations in the zero page - easily done with null/bad pointers - would change the operating system's jump vectors, causing all kinds of bizarre crash behavior - everything from locked-out keyboards and blinking video screens full of garbage to hard drive light flashing frenzy, blue screen of death, rebooting, etc.

[coding in assembly language was even more fun]

Steven A. Lowe
A: 

Back in college I was tasked on creating a multi-threading proxy.

From time to time, the proxy wasn't responding any of the resources the page pulled. The code causing the issue:

Some code with overflow issues, that used variables near a file handler. Before knowing what was happening, I found it really weird that moving the file handler declaration "fixed" the issue, lol.

Ps. check this one (not in c, but a good story :)): http://trixter.wordpress.com/2006/02/02/computing-myth-1-software-cannot-damage-hardware/

eglasius
A: 

If the software in question is running on a PC, it may "merely" bring down your computer.

If, however, it's controlling the operation of the engine in your car -- or worse, the ABS -- it won't just be the software that crashes...

Steve Melnikoff
A: 

A crash is not the worst thing that can happen.

I read about an old Unix file compression program (you know, like Zip) that didn't check the return value from fclose. Yes, fclose can return an error. Output to a file is normally buffered, so even if a call to fwrite or putc seems to work, and returns OK, the data may still be in a buffer, waiting to be written. When fclose is called, any unwritten data is flushed, and this may fail, since (for example) the disk may be full. And since the compression program was usually run just because the disk was nearly full, this happened rather often. So the program silently truncated the new, compressed file, the original uncompressed file was removed, and the next year or so when someone tried to uncompress the file, the end was missing!

I think this is a good example of why throwing exceptions can be good thing.

Thomas Padron-McCarthy