I had a problem, maybe someone will be able to help, this is a deck program, with the possibility of adding and removing numbers from both the end and the beginning of the list. When I work and compile it in xcode, everything works fine without any complaints. When I run the compiler through the command line, a segmentation fault 11 occurs. What could be the reason and how to look for these segmentation errors? Thanks in advance for your help (ps .h file is not added to the listing but it exists :)))

#include <stdlib.h> #include "dequeue.h" dequeue* dequeue_create() { dequeue *new_dequeue = (dequeue*) malloc(sizeof(dequeue)); //new_dequeue->next = new_dequeue->prev = new_dequeue->last = new_dequeue->first = NULL; return new_dequeue; } void dequeue_push_front(dequeue** dq, int data) { // TODO: add a new element at the beginning of the queue dequeue *new_dequeue = (dequeue*) malloc(sizeof(dequeue)); if (new_dequeue == NULL) { exit(1); } if ((*dq)->prev == NULL ) { (*dq)->prev = new_dequeue; (*dq)->next = new_dequeue; } else { (*dq)->prev->prev = new_dequeue ; new_dequeue->next = (*dq)->prev; (*dq)->prev = new_dequeue; } new_dequeue->data = data; new_dequeue->prev = NULL; } void dequeue_push_back(dequeue** dq, int data) { // TODO: add a new element at the end of the queue dequeue *new_dequeue = (dequeue*) malloc(sizeof(dequeue)); if (new_dequeue == NULL) { exit(1); } if ((*dq)->next == NULL ) { (*dq)->prev = new_dequeue; (*dq)->next = new_dequeue; } else{ (*dq)->next->next = new_dequeue; new_dequeue->prev = (*dq)->next; (*dq)->next = new_dequeue; } new_dequeue->data = data; new_dequeue->next = NULL; } int dequeue_pop_front(dequeue** dq) { // TODO: retrieve the data of the first element and remove it from the queue // return zero if queue is empty int ret_numb; dequeue *p_dequeue; if( (*dq)->prev == NULL && (*dq)->next == NULL) { return 0; } if( (*dq)->prev == (*dq)->next){ ret_numb = (*dq)->prev->data; free((*dq)->prev); (*dq)->prev = (*dq)->next = NULL; return ret_numb; } ret_numb = (*dq)->prev->data; p_dequeue = (*dq)->prev->next; p_dequeue->prev = NULL; free((*dq)->prev); (*dq)->prev = p_dequeue; return ret_numb; } int dequeue_pop_back(dequeue** dq) { // TODO: retrieve the data of the last element and remove it from the queue // return zero if queue is empty int ret_numb; dequeue *p_dequeue; if( (*dq)->prev == NULL && (*dq)->next == NULL) { return 0; } if( (*dq)->prev == (*dq)->next){ ret_numb = (*dq)->prev->data; free((*dq)->next); (*dq)->prev = (*dq)->next = NULL; return ret_numb; } ret_numb = (*dq)->next->data; p_dequeue = (*dq)->next->prev; p_dequeue->next = NULL; free((*dq)->next); (*dq)->next = p_dequeue; return ret_numb; return 0; } void dequeue_destroy(dequeue** dq) { // TODO: destroy the queue, // free everything so that no memory leak occurs if((*dq)->next == NULL && (*dq)->prev == NULL ) { free(*dq); } else{ dequeue *p_dequeue; do{ p_dequeue = (*dq)->prev->next; free((*dq)->prev); (*dq)->prev = p_dequeue; } while ((*dq)->prev != (*dq)->next); free((*dq)->prev); free(*dq); } } 

Main function

 #include <stdio.h> #include "dequeue.h" int main() { dequeue* dq = dequeue_create(); dequeue_push_front(&dq, 1); dequeue_push_back(&dq, 2); dequeue_push_front(&dq, 3); dequeue_push_back(&dq, 4); dequeue_push_back(&dq, 15); dequeue_push_back(&dq, 32); dequeue_push_front(&dq, 98); for (int cnt = 1; cnt <= 7; cnt++) { printf("%d ", dequeue_pop_front(&dq)); } printf("\n"); dequeue_destroy(&dq); printf("\n"); return 0; } 
  • And what can be seen under the debugger (on which line it drops, because of what action), what does valgrind say? - PinkTux
  • Maybe I have a stupid compiler in the command line (I don’t know how to use it, I always work in xcode), but it doesn’t particularly shine with the information content "wl-c-21: leak-check a1 $ ./double_ended_queue.out Segmentation fault: 11" that's all he says - Anton Barinov

1 answer 1

This feature

 dequeue* dequeue_create() { dequeue *new_dequeue = (dequeue*) malloc(sizeof(dequeue)); //new_dequeue->next = new_dequeue->prev = new_dequeue->last = new_dequeue->first = NULL; return new_dequeue; } 

does not initialize the fields of the created element of type dequeue , such as, for example, prev or next .. Therefore, the call to the function dequeue_push_front has undefined behavior.

 void dequeue_push_front(dequeue** dq, int data) { // TODO: add a new element at the beginning of the queue dequeue *new_dequeue = (dequeue*) malloc(sizeof(dequeue)); if (new_dequeue == NULL) { exit(1); } if ((*dq)->prev == NULL ) ^^^^^^^^^^ { (*dq)->prev = new_dequeue; (*dq)->next = new_dequeue; } //... 

It would be better if the dequeue_create function simply returned NULL , and all other functions, such as dequeue_push_front , dequeue_push_front check if the value of *dq NULL and act in accordance with this test.

  • Thank you for the prompt response, but in more detail, what does it mean that it does not "initialize the field"? and how can this be fixed? - Anton Barinov
  • Just add something from the category new_dequeue-> next = new_dequeue-> prev = NULL; ? - Anton Barinov
  • @AntonBarinov For example, the prev field of the created element with the dequeue_create function is undefined. - Vlad from Moscow
  • Just add something from the category new_dequeue-> next = new_dequeue-> prev = NULL; and new_dequeue-> data = 0; ? - Anton Barinov
  • thanks, figured it out, now it works - Anton Barinov