In lines 75-79, you unconditionally delete the head if it's the only node in the list. What if id != head->st.id in that case? As for successfully deleting the first node when it matches the id, consider adding another clause between lines 79 and 80 that handles a true deletion of a matching head:
else if (id == head->st.id)
tmp = head;
head = head->link;
This will reseat the head to the 2nd node in the list, and then release memory for the old head.