首页 > 解决方案 > 在 Glib 队列中存储结构

问题描述

我有一个错误,其中从 glib 队列中弹出的结构丢失了一些分配的数据。

结构如下:

typedef struct src_file {
    off_t size;
    int filename;
    const char *file_path;
} src_file;

new_src_file()定义为:

src_file* new_src_file(const char * src_filepath, off_t size, int filename) {
    src_file *sh_src_file = malloc(sizeof(src_file));
    sh_src_file->file_path = src_filepath;
    sh_src_file->size = size;
    sh_src_file->filename = filename;
    return sh_src_file;
}

这由 nftw 回调函数填充,该回调函数还将对象推送到队列中

  src_file *sh_src_file = new_src_file(fpath, statptr->st_size, pfwt->base);
  g_queue_push_tail(sh_file_list, sh_src_file);
  

这个结构包含我们试图用 src_file 结构填充的 Gqueue。sh_file_list是使用 nftw 所需的全局队列。它被复制到new_src_handler()

typedef struct src_handler {
    GQueue* src_list;
    off_t src_size;
} src_handler;

src_handler* new_src_handler(char* src_path) {
    sh_total = 0;
    src_handler *sources = malloc(sizeof(src_handler));
    sources->src_list = g_queue_new();
    sh_file_list = g_queue_new();
    int fd_limit = 5;
    int flags = FTW_CHDIR | FTW_DEPTH | FTW_MOUNT | FTW_PHYS;
    int ret = nftw(src_path, process, fd_limit, flags);
    sources->src_size = sh_total;
    sources->src_list = g_queue_copy(sh_file_list);
    g_queue_free(sh_file_list);
    return sources;
}

通过调试器查看变量表明正在存储结构中的所有信息。

这个队列被另一个函数用来处理存储在其中的文件。我将头从队列中弹出并将其存储在临时 src_file 结构中,file_path 被传递给另一个函数,但它作为“”从队列中出来。

int process(...) {
    src_file *src = g_queue_pop_head(copy_job->source_files->src_list);

    printf("%.2f\n", src->size);
    printf("%d\n", src->filename);
    printf("%s\n", src->file_path);
    ...
    return 0;
}

输出:

Scanning Source: /home/user/Downloads/
Total entries: 2
Total Size 128.00
Filename: 23
File Path: 

我不明白 file_path 变量发生了什么,为什么它没有正确地从队列中弹出?调试器显示所有数据在被推送到队列时都存在。我做错了什么还是有一些数据被覆盖在内存中?

调试器输出

调试器输出

第一个图像是调试器的输出,就像sh_src_file被推入队列一样

其次是当它从队列中弹出时。值 12 和 23 结转,但 file_path 是“”,它应该是一个路径。

添加了一些更多的调试消息问题似乎与g_queue_copy()函数有关,如new_src_handler()在 nftw 完成其回调函数后发生了一些奇怪的事情中所见。

int process(const char *fpath, const struct stat *statptr, int flags, struct FTW *pfwt) {
    if(flags == FTW_F) {
        if(strcmp(fpath + pfwt->base, ".DS_Store") != 0) {
            src_file *sh_src_file = new_src_file(fpath, statptr->st_size, pfwt->base);
            g_queue_push_head(sh_file_list, sh_src_file);
            src_file *temp = g_queue_peek_head(sh_file_list);
            printf("Pushed %s onto the queue\n", temp->file_path);
            sh_total += sh_src_file->size;
        }
    }
    return 0;
}

输出确认这些已被推送到队列中:

Pushed /home/howard/Downloads/test.txt onto the queue
Pushed /home/howard/Downloads/testtwo.txt onto the queue

然而:

src_handler* new_src_handler(char* src_path) {
    sh_total = 0;
    src_handler *sources = malloc(sizeof(src_handler));
    sources->src_list = g_queue_new();
    sh_file_list = g_queue_new();
    int fd_limit = 5;
    int flags = FTW_CHDIR | FTW_DEPTH | FTW_MOUNT | FTW_PHYS;
    
    int ret = nftw(src_path, process, fd_limit, flags);
    //re-entry after process()
    
    sources->src_size = sh_total;
    
    //copy global sh_file_list populated by process() to our structure
    sources->src_list = g_queue_copy(sh_file_list); 
    
    //debugging
    src_file *_test = g_queue_peek_head(sources->src_list);
    src_file *_gtest = g_queue_peek_head(sh_file_list);
    
    printf("Peeking sh_file_list (global pre-copy) head: %s\n", _gtest->file_path);
    printf("Peeking src_list head: %s\n", _test->file_path);
    
    g_queue_clear(sh_file_list);
    return sources;
}

输出 process() 中队列中的内容与 new_src_handler() 中查看的内容不同:

Peeking sh_file_list (global pre-copy) head: /home/howard/Downloads
Peeking src_list head: /home/howard/Downloads

标签: cqueueglib

解决方案


修改 new_src_handlerg_strdup解决了这个问题。


推荐阅读