2017-07-04 91 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'形式,因为它避免了副本。 –