As many young programmers do, I learned the usefulness of inserting numerous print-to-console statements of "here1," "here2," and so on at different points in code to figure out when my programs are going awry. This brute force debugging technique has saved me many, many times throughout my CS studies. However, when I started programming in C, I stumbled onto an interesting problem. If I were to try and run
void* test;
printf("hello world");
test[5] = 234;
Of course I get a segfault for not malloc'ing memory for testChar. However, you would think logically that "hello world" would be printed before the seg fault happens, since that is the flow of the code, but in my experience, it is always the case that the seg fault happens first, and "hello world" is never printed to the console at all. (I wasn't able to test this exact example, but I have run into this sort of situation many times using gcc on a linux box.) I'm guessing this has to do with either the compiler rearranging some things and/or printf using some sort of buffer that is flushed asynchronously and therefore not being immediate. This is entirely speculation on my part because I honestly don't know why it happens. In any other language that I have used, no matter what problem the "testChar =..." line caused, the "hello world" would still be printed, and thus I could determine where the problem is.
My question is why does this happen when I'm programming C? Why isn't the hello world printed first? And secondly, is there a better C programming debugging technique than this that accomplishes the same basic thing? As in, an easy/intuitive way to find the line of code that is a problem?
Edit: I gave a working example by accident haha. What I have now should cause a segfault. It's funny how usually when I don't want a segfault I get one, and now when I actually wanted one I wrote legal code!
The code you posted is perfectly legal and should not cause a segfault - there is no need to malloc anything. Your problem must lie somewhere else - please post the smallest example of code that causes the problem.
Edit: You have now edited the code to have a totally different meaning. Still, the reason that "hello world" is not displayed is that the the output buffer has not been flushed. Try addinig
after the printf.
Regarding locating the source of the problem you have a couple of choices:
__FILE__
and__LINE__
C macrosprintf
writes to stdout, which is buffered. Sometimes that buffer doesn't get flushed before your program crashes so you never see the output. Two ways to avoid this:fprintf( stderr, "error string" );
since stderr is not buffered.fflush( stdout );
after the printf call.As Neil and others have said, the code as written is fine. That is, until you start modifying the buffer that
testChar
points to.The output is buffered by default, the segfault occurs before the output is actually written to stdout. Try:
(stderr is unbuffered by default.)
"As in, an easy/intuitive way to find the line of code that is a problem?"
Use gdb (or any other debugger).
To find where your program seg faults you compile it with
-g
option (to include debugging symbols) run your application from gdb, it will stop on seg fault.You can then look at backtrace with
bt
command to see at which point you got the seg fault.example:
You have two problems. The first is that your (original) code won't segfault. It's perfectly valid to assign that string constant to a char pointer. But let's leave that aside for now and pretend you had put something there that would segfault.
Then it's usually a matter of buffers, the one in the C runtime library and the one in the OS itself. You need to flush them.
The easiest way to do that was (in UNIX, not entirely certain about the
fsync
in Linux but you should be guaranteed that this wil happen eventually unless the system itself goes down):I've done this often in UNIX and it ensures that the C runtime libraries are flushed to UNIX (
fflush
) and the UNIX buffers are sync'ed to disk (fsync
), useful if stdout is not a terminal device or you're doing it for a different file handle.Its likely that "hello world" is being buffered by the system somewhere and is not immediately printed to the screen. Its stored waiting for a chance for whatever process/thread/whatever is in charge of screen writing can have a chance to process it. And while its waiting (and possibly buffering other data to output) you're function is finishing. It comes over the illegal access and segfaults.