contributed by < Superdanby
>
sudo dnf install cppcheck colordiff
queue_t *q_new()
The first problem I encountered is whether I should type cast the memory returned from malloc. If I remembered right, there would be a warning/error if one didn't do it. Thus, I searched and found that it is suggested not doing so in C.
Note that C and C++ have different behaviors on this issue.
void q_free(queue_t *q)
Needs to iterate through the queue and release the memory of value entry of each element.
bool q_insert_head(queue_t *q, char *s)
Should also link tail if tail is empty.
bool q_insert_tail(queue_t *q, char *s)
, O(1)Should also link head if head is empty.
bool q_remove_head(queue_t *q, char *sp, size_t bufsize)
The first things I was thinking is that if I allocate sp
a new block of memory with malloc
, the caller will not receive the returned string. And then, I saw bufsize, which is when I realized the caller will malloc
on its side.
int q_size(queue_t *q)
, O(1)Add a new entry in queue_t, and this could be done in O(1).
void q_reverse(queue_t *q)
Should not allocate or release memory.
Needs to traverse the whole queue and reverse each element one by one.
ERROR: Failed to store removed value
After checking my code, I found that the if
statement I used to check whether to copy head->value
to sp
in bool q_remove_head(queue_t *q, char *sp, size_t bufsize)
is wrong.
Wrong version:
Corrected version:
The reason why I code it wrong is because I wanted to write sp != NULL
, but I gone lazy and make it !sp
which is really stupid. I should be more cautious next time.
ERROR: Freed queue, but 1 blocks are still allocated
Wrong version:
Corrected version:
temp->value
needs to be cleared even if it couldn't be copied to sp
.
Looking at Makefile
, we can see that the make test
executes scripts/driver.py
.
driver.py
run
methodIncrements the total score by the corresponding value in maxScores
if no error detected after executing runTrace
; the total score will not be incremented otherwise.
runTrace
methodExecutes qtest
with different arguements composed in clist
qtest
allocation_check()
.error_check()
.bool error_check()
Checks if an error had occured and clears error_occurred
.
size_t allocation_check()
Returns the number of blocks of memory still allocated. The number is actually stored in allocated_count
and is incremented and decremented in test_malloc
and test_free
respectively. Thus, we can infer from this fact that all operations for memory allocation / release will be tested with these 2 functions.
Searching all files with find . -exec grep 'test_free\|test_malloc' {} + 2> /dev/null
, we get the following result:
From the result, we can know that all files which include harness.h
have there free()
and malloc()
from standard library replaced with those of harness.h
.
Next, using find . -exec grep '#include "harness.h"' {} + 2> /dev/null
, we can see the following:
The file queue.c
we were modifying is also using "harness.h"
char *test_strdup(const char *s)
This function utilizes test_malloc
to allocate memory, copies the contents of s
to the newly allocated memory, and returns it. #define strdup test_strdup
is also written in line 61 in "harness.h"
. It seems that we should use this function in q_remove_head
to return the string being deleted.
But, the operation returns a new address other than the given one recorded in sp
of bool q_remove_head(queue_t *q, char *sp, size_t bufsize)
. Thus, the caller of bool q_remove_head
would never get q->head->value
in sp
if the implementation is sp = strdup(q->head->value)
void sigsegvhandler(int sig)
Triggers when there is a segementation fault with SIGSEGV
.
void sigalrmhandler(int sig)
Triggers when time limit exceeded with SIGALRM
.
bool exception_setup(bool limit_time)
Saves states and sets up alarm
.
State is saved in line 1. It can later be recovered with siglongjmp
in void trigger_exception(char *msg)
if any exception is triggered.
From man alarm
:
alarm()
arranges for a SIGALRM signal to be delivered to the calling process inseconds
seconds.
Ifseconds
is zero, any pending alarm is canceled.
In any event any previously setalarm()
is canceled.
In line 17, time limit is set with limit_time
, which is a bool
type. So, the time limit is 1 second if time limit is set.
This function results in the behavior of ERROR: Time limit exceeded. Either you are in an infinite loop, or your code is too inefficient
when --valgrind
option is set, meaning valgrind
affects the execution time of each operation: