Ubuntu 22.04下C++中inotify_event的name为空问题求助
inotify代码C++编译无printf输出,C编译正常的原因分析
问题背景
在Ubuntu 22.04系统中,基于inotify开发的监控代码,存为C文件用gcc 11.3编译时,创建文件能正常输出提示;但存为C文件用g 11.3编译时,printf("File %s is created/moved", event->name);无任何输出。代码如下:
#include <sys/inotify.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #define EVENT_SIZE sizeof(struct inotify_event) #define EVENT_BUF_LEN 1024 int main() { int wd, fd = inotify_init(); /* (0) Init inotify */ if (fd < 0) { printf("Unable to inizialize inotify()"); return 1; } wd = inotify_add_watch(fd, "/home/chao/Desktop/new_dir/", IN_MODIFY | IN_CREATE | IN_DELETE); if(wd < 0) { perror(""); return 1; } while (1) { char buffer[EVENT_BUF_LEN]; int i, length = read(fd, buffer, EVENT_BUF_LEN); if (length < 0) { printf("Iwatch error"); continue; } else i = 0; while (i < length) { struct inotify_event *event = (struct inotify_event *)malloc(EVENT_SIZE); memset(event, 0, EVENT_SIZE); memcpy(event, &buffer[i], EVENT_SIZE); if (event->len) { if (event->mask & IN_ISDIR) { printf("Directory %s created/moved", event->name); /* Nothing to do */ } else { printf("File %s is created/moved", event->name); // handle files... } } i += EVENT_SIZE + event->len; free(event); // 原代码遗漏该语句,存在内存泄漏 } } inotify_rm_watch(fd, wd); close(fd); return 0; }
原因分析
1. 标准输出缓冲策略差异
C和C++对stdout的缓冲处理存在细微区别:
- 终端设备默认采用行缓冲,只有输出遇到换行符
\n,或调用fflush(stdout)时,才会将缓冲内容刷新到终端。 - 在C中,当程序阻塞在
read(等待inotify事件)前,可能触发了stdout的隐式刷新(例如系统调用前后的缓冲同步),因此即使没有换行符也能输出内容。 - 在C++中,这种隐式刷新的触发条件更严格,未换行的输出会被留在缓冲中,直到缓冲满或程序退出才会显示,导致无法看到实时输出。
2. 冗余内存操作的潜在风险
原代码中通过malloc分配event内存再memcpy的操作完全多余:inotify的事件数据直接存储在read返回的buffer中,无需额外拷贝。虽然这在C中通常不会出错,但在C++中,额外的内存拷贝可能因对齐规则、内存初始化的细微差异,导致event->name的读取异常(不过这不是本次问题的主要原因)。同时原代码遗漏了free(event),会导致持续的内存泄漏。
解决方法
方法一:修复输出缓冲问题
在printf语句末尾添加换行符\n(推荐),或手动调用fflush(stdout)强制刷新:
// 添加换行符 printf("File %s is created/moved\n", event->name); // 或手动刷新缓冲 printf("File %s is created/moved", event->name); fflush(stdout);
方法二:优化事件读取逻辑
去掉冗余的malloc、memcpy和free操作,直接对buffer中的数据进行类型转换:
while (i < length) { struct inotify_event *event = reinterpret_cast<struct inotify_event*>(&buffer[i]); if (event->len) { if (event->mask & IN_ISDIR) { printf("Directory %s created/moved\n", event->name); } else { printf("File %s is created/moved\n", event->name); // handle files... } } i += EVENT_SIZE + event->len; }
内容的提问来源于stack exchange,提问作者jcraffael
相关产品推荐
相关产品推荐

