You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 15:25:05