2017-07-04 92 views
-2

我試圖通過C語言中的數組和指針實現隊列。隊列 被C結構C指針隊列中的指針

// Circular Buffer 
typedef struct{ 
    main_controller_req_t  buffer[BUFFER_SIZE]; // buffer 
    uint16_t     size;     // length of the queue 
    uint16_t     count;     // number of elements present in the queue 
    main_controller_req_t  *p_head;    // pointer to head of the queue (read end) 
    main_controller_req_t  *p_tail;    // pointer to tail of the queue (write end) 
}circular_buffer_t; 

我已經實現功能,用於隊列初始化

void init_cb(circular_buffer_t *p_cb){ 

    p_cb->p_head = p_cb->buffer; 
    p_cb->p_tail = p_cb->buffer; 
    p_cb->count = 0; 
    p_cb->size = BUFFER_SIZE; 

} 

和功能,用於插入到所述隊列建模

BOOL enqueue_cb(circular_buffer_t *p_cb, main_controller_req_t *p_enq_elem){ 

    if(p_cb->count < p_cb->size){ 

     // queue contains at least one free element 

     taskENTER_CRITICAL(); 

      // insert the element at the tail of queue 
      *(p_cb->p_tail) = *p_enq_elem; 
      // incrementing modulo size 
      p_cb->p_tail = (((p_cb->p_tail++) == (p_cb->buffer + p_cb->size)) ? (p_cb->buffer) : (p_cb->p_tail)); 
      // one element added 
      p_cb->count++; 

     taskEXIT_CRITICAL(); 

     return TRUE; 

    }else{ 

     // queue is full 
     return FALSE; 

    } 

} 

的enqueue_cb功能運作良好,直到尾部達到BUFFER_SIZE。然後 程序崩潰,uC重置。問題是在p_tail指針更新,但我不明白爲什麼 。請任何人都可以幫助我?提前致謝。

+1

我建議你在你的電腦(Visual Studio或類似的)上執行所有不依賴於CPU的庫。它將減輕您的調試併產生更少的問題。 – tilz0R

+1

請提供您的使用導致崩潰的主要功能的一小部分。 –

+1

@Steve>你不能在同一語句中分配p_cb-> p_tail **和**使用'++'。 (很公平,你可以,你只是讓你的代碼難以理解,即使是你自己也是如此) – spectras

回答

0

問題出在您的測試中......您檢查溢出,但在之前遞增指針,這會導致p_cb->p_tail越過循環緩衝區的末端。

p_cb->p_tail = ((p_cb->p_tail++) == (p_cb->buffer + p_cb->size)) 
        ? (p_cb->buffer) 
        : (p_cb->p_tail); 

必須經過遞增測試尾巴的價值。

p_cb->p_tail = (++(p_cb->p_tail) >= (p_cb->buffer + p_cb->size)) 
        ? p_cb->buffer 
        : p_cb->p_tail; 

順便說一句,鏈表不是一個非常有效的實現循環緩衝區的方法。你有沒有考慮過使用一個簡單的fifo緩衝區實現?

fifo構造非常常見,對於C有一個通用宏實現是有用的。如果只有一個生產者和一個使用者,它是線程安全的(不需要鎖)。

這些宏很容易被編譯器優化。

這是一個在工具箱中使用的好工具。

// save these macros in a header file. 
#define fifo_reset(fifo) \ 
    { (fifo).head = (fifo).tail = (fifo).buffer; } 

#define fifo_elements(fifo) \ 
    (sizeof((fifo).buffer)/sizeof((fifo).buffer[0]) 

#define fifo_count(fifo) \ 
    (((fifo).tail >= (fifo).head)) ? ((fifo).tail - (fifo).head) : (((fifo).tail - (fifo).head) + fifo_elements(fifo)) 

#define fifo_free_space(fifo) \ 
    (fifo_elements(fifo) - (fifo_count(fifo) + 1)) 

#define __fifo_advance(fifo, ptr) /* this is "private" */\ 
    ((((ptr) + 1) < (fifo).buffer + fifo_elements(fifo))) ? ((ptr) + 1) : (fifo).buffer) 

#define fifo_full(fifo) \ 
    (__fifo_advance(fifo, (fifo).head) == (fifo).tail) 

#define fifo_empty(fifo) \ 
    ((fifo).head == (fifo).tail) 

#define fifo_pop(fifo, el) \ 
    ((fifo).head = ((el) = *(fifo).head, __fifo_advance(fifo, (fifo).head))) 

#define fifo_push(fifo, el) \ 
    ((fifo).tail = (*((fifo).tail) = (el), __fifo_advance(fifo, (fifo).tail))) 

// Now, any struct with head, tail, and fixed-length buffer is a fifo. 
struct char_fifo_128 
{ 
    char buffer[128]; 
    char* head; 
    char* tail; 
}; 

struct main_controller_req_t 
{ 
    // all data types are _movable_ using '=' 
    char any[128]; 
    int data; 
    float more_data; 
    char* dupstr; 
}; 

#define BUFFER_SIZE 256 

struct controller_fifo 
{ 
    main_controller_req_t  buffer[BUFFER_SIZE]; // buffer 
    main_controller_req_t* head; 
    main_controller_req_t* tail; 
}; 

int main() 
{ 
    char c = 0; 
    int elements_stored; 
    controller_fifo queue; 
    main_controller_req_t req; 

    fifo_reset(queue); // MUST call before using fifo 

    // always check if space/data is available. 
    if (!fifo_full(queue)) 
    { 
     fifo_push(queue, req); 
    } 
    elements_stored = fifo_count(queue); 

    if (!fifo_empty(queue)) 
    { 
     fifo_pop(queue, req); 
    } 

    fifo_reset(queue); // fifo reset is NOT thread-safe 


    char_fifo_128* buffer = (char_fifo_128*)malloc(sizeof(char_fifo_128)); 

    fifo_reset(*buffer); 

    if (!fifo_full(*buffer)) 
    { 
     // ... 
     fifo_push(*buffer, req); 
    } 
    elements_stored = fifo_count(*fifo); 

    if (!fifo_empty(*buffer)) 
    { 
     fifo_pop(*buffer, c); 
    } 

    free(buffer); 
    return 0; 
} 
+0

非常感謝邁克爾羅伊。 – Steve

+0

@Steve。我的榮幸,Info在答覆中補充道。 @spectras:++運算符具有明確定義的語義:'++ i'遞增'i'並返回遞增的值。 'i ++'複製'i',遞增'i',然後在增量之前返回由'i'組成的副本的值。這就是爲什麼建議使用'++ i'形式,因爲它避免了副本。 –