Здравствуйте, у меня есть небольшая проблема с 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;
}
Я полагаю, что проблема с тетсром он копирует только указатель на структуру хранится в данных и не содержало поле указателей. Таким образом, первый элемент можно сохранить, но остальные потеряны. Мне нужно скопировать, поскольку pop_back удаляет и освобождает данные от узла в связанном списке –
'int task_size = sizeof (task)' <- это не может быть прав: 'sizeof * task' - я думаю, что вы хотите, и при любом rate: 'sizeof' возвращает' size_t', а не 'int'. Также задание 'task_t *; task = (task_t *) tmp_data; 'выглядит уродливо. Почему бы не 'task_t * task = tmp_data;'. Нет необходимости в литье. Это чистый, легкий для чтения однострочный –
Да, но это task_t - это только тестовый код. Я помещаю его, чтобы показать, что когда он обложен реальным типом task_t * (структуры), он имеет все заполненные поля, но когда я просто работаю на void * (общий тип), и я его копирую, а затем возвращаю как void *, тогда я теряя поля, даже если позже к тем же актам. Я думаю, что это эффект memcpy void * не реального типа. Бу, я не знаю, как компенсировать эту проблему. Я не хочу потерять родословные в моей очереди с fifo и связанным списком, также не хочу путаться с помощью аддитальных типов, чтобы сделать эту копию безопасной. –