【问题标题】:How can I make my program compile without warning?如何让我的程序在没有警告的情况下编译?
【发布时间】:2015-05-10 07:12:12
【问题描述】:

我应该将带有规范标志的程序编译为 gcc。然后 gcc 抱怨没有处理返回值。当我使用变量获取返回值时,gcc 再次抱怨:

$ gcc -pedantic -Wall -ansi -O4 miniShell.c
miniShell.c: In function ‘cd’:
miniShell.c:108:9: warning: variable ‘other_return’ set but not used [-Wunused-but-set-variable]
     int other_return;
         ^
miniShell.c:107:12: warning: variable ‘return_value’ set but not used [-Wunused-but-set-variable]
     char * return_value;
            ^

如何解决这些警告?我的程序如下。

#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <dirent.h>
#include <errno.h>
#include <stdarg.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>

#define BUFFER_LEN 1024
#define BUFFERSIZE 1024


int mystrcmp(char const *, char const *);


void err_syserr(char *fmt, ...)
{
    int errnum = errno;
    va_list args;
    va_start(args, fmt);
    vfprintf(stderr, fmt, args);
    va_end(args);
    if (errnum != 0)
        fprintf(stderr, "(%d: %s)\n", errnum, strerror(errnum));
    exit(EXIT_FAILURE);
}
int main() {
    char line[BUFFER_LEN];  
    char* argv[100];        
    char* path= "/bin/";    
    char progpath[20];      
    int argc;               
    size_t length;
    char *token;
    int i=0;
    int pid;
    while(1) {
    i = 0;
        printf("miniShell>> ");                    

        if(!fgets(line, BUFFER_LEN, stdin)) { 
            break;                                
        }
        length = strlen(line);
        if (line[length - 1] == '\n') {
            line[length - 1] = '\0';
        }
        if(strcmp(line, "exit")==0) {           
            break;
        }


        token = strtok(line," ");

        while(token!=NULL) {
            argv[i]=token;
            token = strtok(NULL," ");
            i++;
        }
        argv[i]=NULL;                     

        argc=i;                           
        for(i=0; i<argc; i++) {
            printf("%s\n", argv[i]);      
        }
        strcpy(progpath, path);           
        strcat(progpath, argv[0]);            

        for(i=0; i<strlen(progpath); i++) {   
            if(progpath[i]=='\n') {
                progpath[i]='\0';
            }
        }
        pid= fork();              

        if(pid==0) {              
            execvp(progpath,argv);
            fprintf(stderr, "Child process could not do execvp\n");

        } else {                  
            wait(NULL);
            printf("Child exited\n");
        }

    }
return (0);
}

int mystrcmp(char const *p, char const *q)
{
    int i = 0;
    for(i = 0; q[i]; i++)
    {
        if(p[i] != q[i])
            return -1;
    }
    return 0;
}

int cd(char *pth) {
    char path[BUFFERSIZE];
    char cwd[BUFFERSIZE];
    char * return_value;
    int other_return;
    strcpy(path,pth);

    if(pth[0] != '/')
    {  
        return_value = getcwd(cwd,sizeof(cwd));
        strcat(cwd,"/");
        strcat(cwd,path);
        other_return = chdir(cwd);
    } else { 
        other_return = chdir(pth);
    }
    printf("Spawned foreground process: %d\n", getpid());
    return 0;
}

【问题讨论】:

  • 要么使用这些变量,要么删除它们。
  • @Mat 我没有使用变量,但它们不会收到警告,因为如果我省略返回值的变量,gcc 会抱怨。我不知道不会产生警告的选项。
  • 好吧,那就用它们吧。您调用的函数可能会失败。检查失败。

标签: c linux gcc compilation compiler-warnings


【解决方案1】:

在字里行间,我猜你试图解决的原始问题是一个警告:

 warning: ignoring return value of ‘chdir’

您已尝试通过将返回值分配给变量(该变量本身现在未使用)来解决此问题。

getcwdchdir 在失败时都可以返回错误代码,这是 GCC 警告您的返回值。如果您想正确修复警告,您应该在代码中添加逻辑以检测和处理这些错误情况。否则,您可能会继续处于与您的假设不一致的状态(例如,如果 getcwd 失败并使您的缓冲区处于未正确初始化的状态,您可能会处于意外目录中)。

我曾认为可以通过将函数调用的结果强制转换为 void 来覆盖它,但这不起作用(您仍然可以玩花样,但它们会变得混乱!)。 warn_unused_result 属性的 GCC 文档说:

warn_unused_result 属性会导致发出警告,如果 具有此属性的函数的调用者不使用其返回 价值。这对于不检查结果的函数很有用 要么是安全问题,要么总是错误,

这表明您不想为警告找到解决方法,而实际上应该检查返回值是否存在错误情况。

如果你真的想这样做,将结果分配给你所做的变量,然后添加对该变量的一次使用,强制转换为 void:

int res = chdir (cwd);
/* I promise I don't need to check this return value.  */
(void) res;

【讨论】:

    【解决方案2】:

    其他用户已经回答了如何通过修复代码来消除警告,但仅供参考:如果您想“忽略”警告,请使用标志编译:

    -Wno-unused-but-set-variable
    

    编译器通常会在警告结束时为您提供一个标记(在您的情况下,它是 -Wunused-but-set-variable)。要忽略它,只需将 -W 更改为 -Wno-

    希望这会有所帮助!

    【讨论】:

      【解决方案3】:

      您的代码中实际上有两处错误。第一个可能导致您更改代码,然后导致您现在询问的警告。

      我敢打赌,第一个初始警告是关于 chdir。正如文件所说:

      man chdir(3):“成功完成后,应返回 0。 否则返回-1,当前工作 目录应保持不变,errno 应设置为 指出错误。”

      正如它所说,chdir 可以返回一个错误代码,说明是否出现任何问题,并且由于您只是忽略了该值而导致了第一个初始警告。

      然后您更改了代码并将值分配给另一个变量并得到:

      警告:变量“other_return”已设置但未使用 [-Wunused-but-set-variable] int other_return;

      您可以在此函数中看到,您只是为该变量设置了一个值,但以后并没有实际使用它,这意味着您可以将其删除:

      int cd(char *pth) {
      char path[BUFFERSIZE];
      char cwd[BUFFERSIZE];
      char * return_value;
      int other_return;
      strcpy(path,pth);
      
      if(pth[0] != '/')
      {  
          return_value = getcwd(cwd,sizeof(cwd));
          strcat(cwd,"/");
          strcat(cwd,path);
          other_return = chdir(cwd);
      } else { 
          other_return = chdir(pth);
      }
      printf("Spawned foreground process: %d\n", getpid());
      return 0;
      }
      

      return_value 也是如此。你可以简单地删除它们,因为它们都没有被使用。

      如果您想避免第一个初始警告,您可以随时执行以下操作:

      int res = chdir (cwd);
      (void) res;
      

      这是你向编译器保证一切正常,他可以忽略警告。

      【讨论】:

      • man chdir(3): "成功完成后返回0,否则返回-1,当前工作目录不变,设置errno指示错误。"
      猜你喜欢
      • 2015-09-24
      • 1970-01-01
      • 2022-07-20
      • 1970-01-01
      • 2018-01-29
      • 1970-01-01
      • 2021-11-22
      • 1970-01-01
      相关资源
      最近更新 更多