I have a bug where a struct which is popped off a glib queue has lost some of it's assigned data.
the struct is as follows:
typedef struct src_file {
off_t size;
int filename;
const char *file_path;
} src_file;
new_src_file()
is defined as:
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;
}
This is populated by a nftw callback function which also pushes the object onto the queue
src_file *sh_src_file = new_src_file(fpath, statptr->st_size, pfwt->base);
g_queue_push_tail(sh_file_list, sh_src_file);
This structure contains the Gqueue that we are trying to populate with src_file structures. sh_file_list
is the global queue that is needed to work with nftw. It is copied in 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;
}
Looking at the variables via the debugger suggests that all the information within the structure is being stored.
This queue is used by another function to process the files stored within it. I am popping the head off the queue and storing it in a temporary src_file structure, the file_path is passed to another function but it is coming off the queue as "".
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;
}
Output:
Scanning Source: /home/user/Downloads/
Total entries: 2
Total Size 128.00
Filename: 23
File Path:
I don't understand what is going on with the file_path variable, why has that not properly been popped off the queue? The debugger shows that all data was present when it was pushed onto the queue. Am I doing something wrong or is there some data being over written in memory?
First image is the output from the debugger just as the sh_src_file
is pushed onto the queue
Second is when it is popped off the queue. values 12 and 23 carry over but the file_path is "" where it should be a path.
Added some more debugging messages issue appears to be with the g_queue_copy()
function, as seen in new_src_handler()
Something strange is happening after nftw has finished it's callback function.
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;
}
output confirms that these have been pushed onto the queue:
Pushed /home/howard/Downloads/test.txt onto the queue
Pushed /home/howard/Downloads/testtwo.txt onto the queue
However:
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;
}
Output what was on the queue in process() is not the same as what is peeked in the new_src_handler():
Peeking sh_file_list (global pre-copy) head: /home/howard/Downloads
Peeking src_list head: /home/howard/Downloads
Modifying the new_src_handler with g_strdup
solved the issue.