CHANGES.txt
file in the version you have. This file will contain details of the
changes made up to the current version.
malloc
, etc), then it may be better to print out as
descriptive an error message as possible, and terminate the program,
since the error is likely to be unrecoverable.
assert()
function for? When should I
use it? Assert()
is for detecting mistakes and
inconsistencies when you're writing and debugging code. If the
condition in the assert fails, the program prints an error and dumps
core (writes the contents of its memory to a file, for non-Unix
people). For instance, if at at the start of function A, the value of
X should be 2, and the value of Y should be 8, you could put an
"assert(X == 2 && Y == 8)
" at the top. Asserts are useful
for detecting when you made an incorrect assumption about a program
invariant, or you violated the invariant elsewhere in your code. You
should not really use them for catching any of the caller-caused
errors in the previous paragraph.
char* return_a_string(...) { char string[32]; ... return string; } ... int main() { char* x = return_a_string(...); ... } |
x
ends up pointing to some
location on the stack, which may get used for some other data and
overwritten by a later function invocation. Returning this kind of a
pointer is even more dangerous because you might not notice the bug
immediately. If in place of return_a_string
we had
int* return_an_integer(...) { int integer = 32; ... return &integer; } |
STACKSIZE
constant in
minithread_md.h
), or make the array smaller.
minithread.h
, queue.h
, synch.h
,
etc? Can we change files which say "You should not need to
change this file" at the top?
minithread_allocate_stack()
, and initialise it by calling
minithread_initialize_stack()
. Initialising the stack
requires two functions: the function the new thread should run, and a
"final" function, which runs after the main function has returned. The
final function need not be unique for each thread. Both functions have
arguments, so that the order of invocation looks like:
main_proc(main_arg); finally_proc(finally_arg)
. The
exception is the first thread you create, which gets the original
stack for the process, and runs inside
minithread_system_initialize()
. It still needs a thread
control block, however, so that it can participate in context switches
correctly. This first thread cannot terminate in the same way as
the others: since it's running on the NT stack, when it returns from
main()
, it will destroy the whole process.
minithread_start()
and
minithread_stop()
for?
minithread_self()
and
minithread_id()
for?
minithread_start()
on it. Of course,
this is only useful outside minithread.c
. Thread IDs are
really only helpful for debugging.
synch.h
.