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

修复C代码编译报-Wmaybe-uninitialized的pwd未初始化警告

问题原因

这个警告是代码本身存在逻辑缺陷导致的,不是单纯的系统环境差异,你朋友的电脑上没出警告只是编译器版本/编译参数不同没检测出问题,不代表代码没有运行风险。

具体问题点有两个:

  • 局部指针变量pwd声明后没有初始化,只有在stat()调用成功的if分支里才会被赋值。一旦stat()调用失败(比如文件被临时删除、无目标文件读取权限),pwd会保留栈上的随机垃圾值,后续判断if (pwd != 0)的逻辑完全不可靠,甚至可能触发野指针访问导致程序崩溃。
  • 循环里冗余调用了两次stat(),第一次调用完全没有做返回值检查,如果stat()执行失败,my_stat结构体里的字段全是未初始化的垃圾值,后续读取文件大小、修改时间、UID的操作都会输出错误内容,甚至触发内存访问异常。
修改方案
  1. 声明pwd时直接初始化为NULL,保证所有代码路径下它的值都是确定的,直接消除未初始化警告。
  2. 删除第一次无返回值检查的冗余stat()调用,把所有依赖stat()返回结果的逻辑(获取用户信息、格式化时间、打印文件属性)全部放到stat()调用成功的分支内,避免调用失败时读取未初始化的结构体字段。

修正后的可直接编译运行的完整代码如下:

#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#include <pwd.h>
#include <time.h>
#include <errno.h>
#include <string.h>

int list_dir(const char *dir)
{
    struct dirent* cur_directory;
    struct stat my_stat;
    struct tm lt;
    // 声明时直接初始化为NULL,消除未定义值风险
    struct passwd *pwd = NULL;

    DIR* directory = opendir(dir);
    if(directory == NULL) {
        printf("list_dir : %s : %s \n", dir, strerror(errno));
        return 0;
    }

    printf("Directory : %s\n\n", dir);
    while( (cur_directory = readdir(directory)) ) {
        // 移除冗余stat调用,仅保留带返回值检查的一次调用
        if (stat(cur_directory->d_name, &my_stat) == 0) {
            pwd = getpwuid(my_stat.st_uid);
            time_t t = my_stat.st_mtime;
            localtime_r(&t, &lt);
            char timebuf[80];
            strftime(timebuf, sizeof(timebuf), "%c", &lt);
            if (pwd != NULL) {
                printf("%s \t %ld \t %s \t %s\n", pwd->pw_name, (long)my_stat.st_size, timebuf, cur_directory->d_name);
            } else {
                printf("%d \t %ld \t %s \t %s\n", my_stat.st_uid, (long)my_stat.st_size, timebuf, cur_directory->d_name);
            }
        } else {
            // stat调用失败时打印错误信息,方便排查问题
            printf("access %s failed: %s\n", cur_directory->d_name, strerror(errno));
        }
    }
    closedir(directory);
    return 0;
}

int main(int argc, char* argv[]){
    if ( argc == 1 ) {
        return list_dir ( "." );
    } else {
        int ret = 0;
        for (int i = 1; i < argc; i += 1 ) {
            if ( list_dir ( argv[i] ) != 0 ) {
                ret = 1;
            }
        }
        return ret;
    }
}
补充说明

不同编译器、同一编译器的不同版本的控制流分析能力有差异,加上编译时开启的优化等级、警告参数不同,可能出现同一份代码在某台机器上不报警告、在另一台机器上报警告的情况。但只要编译器报了-Wmaybe-uninitialized,就说明代码存在可触发未定义行为的路径,必须修正,不能靠换编译环境绕过警告。

内容的提问来源于stack exchange,提问作者user17978223

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 12:15:34