contributed by < RZHuangJeff
>
linux2021
Impelment following functions in queue.[ch]
:
q_new
: Create a new, empty queue.q_free
: Free all storage used by a queue.q_insert_head
: Attempt to insert a new element at the head of the queue (LIFO discipline).q_insert_tail
: Attempt to insert a new element at the tail of the queue (FIFO discipline).q_remove_head
: Attempt to remove the element at the head of the queue.q_size
: Compute the number of elements in the queue.q_reverse
: Reorder the list so that the queue elements are reversed in order. This function should notallocate or free any list elements.q_sort
: Sort the elements of the given queue in ascending order.q_new
q
is valid before inititalizing its contents.q_free
q
is NULL
Run through entire queue with a temporary variable
cur
and free the space pointed bycur
q_insert_head
q_remove_head
sp
if sp
is not NULL
q_insert_tail
q
is NULL
In order to reach O(1) operation time,
tail
is introduced toqueue_t
, which is type oflist_ele_t**
. The reason why definestail
aslist_ele_t**
is to simplify checking of edge condition such as insert tail in the empty queue.
q_reverse
q
is NULL
or empty or with only one element in it
temp_head
reprecents the head of reversed queue, in each loop round,cur
points to the element would be reverse.
q_size
NULL
or empty queueIn order to reach O(1) operation time,
size
was introduced toqueue_t
, initialized with zero, and will be updated each time an element is inserted or removed viaq_insert_head
,q_insert_tail
orq_remove_head
.
q_sort
NULL
or empty queue as argumentIn order to reach O(nlogn) operation time, merge sort is choosen as the algorithm of implementation.
There are two functions,divide
andmerge
, introduced and will cooperate withq_sort
to fulfill the task.
Functiondivide
aims to cut a queue into two. It first set the size of subqueue(line 15), then run through the list to find the point to cut(for loop around line 19), finally resets all coresponding fields around cut to make divide happend. Notice that there is no checking for edge conditions such asNULL
or the queue with no more than 2 elements in it, since it will only be called byq_sort
, which has already checked such conditions(line 3).
Functionmerge
expects two queues with their elements are both in acensing order as its arguments. To merge these queues, it will run through each elements ina
(for loop between line 32 - 41), find the right place for each element inb
(line 33), and insert them to that place(line 35 - 39). Since that elements inb
are in acensing order, it should only run througha
once. Finally, if there are any element inb
after the for loop, those elements will be attached to the tail ofa
. With the same condition mentioned above, this function does not provide checking for edge condition.
qtest
First, I follow the step mentioned in homework description, which make error happend.
At this moment, I notice several lines of this error message, which helps me to locate where exactly error happends: First, at line 24, after showing Options:
there should be several lines of options. Second, from the stack trace shown by Address Sanitizer(around line 28 - 35), it shows that the error happends at line 306 in file console.c.
Since that the stack trace of Address Sanitizer says that the error happened in do_help_cmd
, not in report
, furthermore, at line 27 of error message shown above, it says that a READ
of size 4 at 0x55d6527d07a0
causes the error.
At this moment, I can roughly determine that *plist->valp
causes the error, since that only field valp
, which has type of int*
, can cause a read of size 4 while dereferencing it and passing it as argument.
Since parm_list
was initialized in function init_cmd
, I turn my attention to this function. According to add_param
in console.c, the parameters in param_list
are ranked with dictionary order, we can find that parameter echo
added at line 106 in console.c causes that error.
At line 58, echo
is defined as type bool
rather than int
. Dereferencing it as int*
may cause the error. To confirm my hypothesis, I comment out line 106, which add option echo
into option list, then following happends:
The same error happended on parameter simulation
, which also defined as type bool
. And both echo
and simulation
are casted to int*
while being added into param_list
.
Since here, I guess that the difference between the size of bool
and int
causes the error. To ensure that, I compile and run the following code(with compile flags -fsanitize=address -fno-omit-frame-pointer -fno-common
).
The program reports that the size of bool
and int
are 1 and 4, respectively. And it also causes the same error while tries to access a
via aptr
(reported at line 6 - 7 in following error messages):
With such evidence, I believe that dereferencing a pointer to int
, which actually points to variable with type bool
, causes the error.
The first solution came up my mind is to redefine echo
and simulation
as type int
. I think this solution works fine to echo
, since it is a static variable, which can only be accessed inside console.c, but not for simulation
, which is defined export in console.h and would be accessed in qtest.c, redefine it will cause a chain effect to recheck files that access it.
Cause the reson mentioned above, I'm still figuring out if there is another solution.