2016-08-02 1 views
0

Здравствуйте, у меня есть небольшая проблема с void *, используемой для создания более общего кода. Я написал fifo queue (используя связанный список внизу), который хранит любые данные, которые могут быть переданы в void * (т. Е. Struct * как void *).Возвращающая структура * хранится в очереди fifo как void * (возвращает ее несколькими функциями)

Теперь у меня есть функция, которая возвращает данные. Но проблема в том, что структура, содержащая 3 поля, возвращается только с заполненным первым заполнением поля, а остальные 2 пустыми (заполняется при размещении в очереди).

Все функции, такие как back(), unwrap'_data_from_node '() и fifo_dequeue(), возвращают эти данные как void *. Более странным является то, что void * может быть отправлен в struct * в fifo_dequeue(), и он будет содержать все поля, заполненные данными, тогда как при возврате из fifo_dequeue() один и тот же возвращаемый указатель имеет только одно заполненное поле (1-е поле) и два пустые, ноль.

void *fifo_dequeue(fifo_queue_t *fifo, size_t *data_size) { 

    doubly_linked_node_t *node; 
    size_t tmp_size; 
    void *tmp_data; 
    void *data; 

    // get data and its size from the last node in the queue 
    if((node = back(fifo->queue)) == NULL) { 
     fprintf(stderr, "back: queue is empty!\n"); 
     data_size = NULL; 
     return NULL; 
    }; 
    tmp_data = unwrap_data(node, &tmp_size); 

    /** HERE I tested casting data to struct test_t and it works properly **/ 
    task_t *task; 
    task = (task_t *) tmp_data; 
    int task_size = sizeof(task); 

    // copy retrieved data 
    data = malloc(tmp_size); 
    memcpy(data, tmp_data, tmp_size); 

    // remove the last node in the queue 
    //pop_back(fifo->queue); 

    if(data_size != NULL) *data_size = tmp_size; // return size of data through pointer argument 
    return data; /** OUTSIDE this pointer casted to struct task_t has empty fields **/ 
} 

Основной метод удаления узла из связанного списка при создании pop_back();

void remove_node(doubly_linked_list_t *list, doubly_linked_node_t *old_node) { 

    // if node to delete unspecified return error 
    if (old_node == NULL) { 
     fprintf(stderr, "Node to delete is empty!"); 
     return; 
    } 

    // if node to delete is the only left on the list make empty list 
    if (old_node->next == old_node) // or old_node->prev = old_node 
    { 
     list->head = list->tail = NULL; 
    } else { 
     old_node->prev->next = old_node->next; 
     old_node->next->prev = old_node->prev; 

     if(old_node == list->head) list->head = old_node->next; 
     if(old_node == list->tail) list->tail = old_node->prev; 
    } 

    free(old_node->data); old_node->data = NULL; 
    free(old_node); old_node = NULL; 
} 
+0

Я полагаю, что проблема с тетсром он копирует только указатель на структуру хранится в данных и не содержало поле указателей. Таким образом, первый элемент можно сохранить, но остальные потеряны. Мне нужно скопировать, поскольку pop_back удаляет и освобождает данные от узла в связанном списке –

+0

'int task_size = sizeof (task)' <- это не может быть прав: 'sizeof * task' - я думаю, что вы хотите, и при любом rate: 'sizeof' возвращает' size_t', а не 'int'. Также задание 'task_t *; task = (task_t *) tmp_data; 'выглядит уродливо. Почему бы не 'task_t * task = tmp_data;'. Нет необходимости в литье. Это чистый, легкий для чтения однострочный –

+0

Да, но это task_t - это только тестовый код. Я помещаю его, чтобы показать, что когда он обложен реальным типом task_t * (структуры), он имеет все заполненные поля, но когда я просто работаю на void * (общий тип), и я его копирую, а затем возвращаю как void *, тогда я теряя поля, даже если позже к тем же актам. Я думаю, что это эффект memcpy void * не реального типа. Бу, я не знаю, как компенсировать эту проблему. Я не хочу потерять родословные в моей очереди с fifo и связанным списком, также не хочу путаться с помощью аддитальных типов, чтобы сделать эту копию безопасной. –

ответ

1

Проблема с sizeof()

Вы только берете размер указателя в этой строке

int task_size = sizeof(task); 

после этого, не хватает данных копируется.

Вы должны таНос и скопировать всю-структуру размера STRUCT:

int task_size = sizeof(task_t); 
+0

Да, но данные, хранящиеся в связанном списке под fifo_queue, являются указателями (void * data) –

+0

, если вы хотите только вернуть указатель, идите вперед. Не нужно ничего копировать. Но если вы хотите скопировать всю структуру, вам нужно скопировать размер структуры. – eyalm

+0

Да, но проблема в том, что я хочу вернуть void * из fifo_dequeue(), чтобы fifo queue могла хранить типизированные типизированные данные и быть повторно используемыми. Я мог бы вернуть только этот указатель tmp_data, а не mamcpy(), но есть еще одна проблема: перед этим появляется pop_back(), который удаляет узел из fifo_queue (связанный список), а затем он освобождает() этот указатель, поэтому я хочу сделать копию Это. Может быть, я должен удалить это освобождение данных –

Смежные вопросы