在 Glib 队列中存储结构

Storing structs in Glib Queues

我有一个错误,从 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

将 new_src_handler 修改为 g_strdup 解决了问题。