2016-02-01 65 views
2

我试图给我的程序一个命令行参数,剥离第一个字符并将剩余的字符串转换为int。但是当我用if (argv[i][0] == 'w')进行测试时,我得到了分段错误。测试字符串中的第一个字符给出分段错误

$ ./program w10 
Segmentation fault 

 

#include <stdbool.h> 
#include <stdio.h> 
#include <unistd.h> 
#include <signal.h> 
#include <argp.h> 
#include <python2.7/Python.h> 


/* If this flag is nonzero, don’t handle the signal right away. */ 
volatile sig_atomic_t signal_pending; 

/* This is nonzero if a signal arrived and was not handled. */ 
volatile sig_atomic_t defer_signal; 

void 
huphandler (int signum) 
{ 
    if (defer_signal) 
    signal_pending = signum; 
    else 
    exit(0); 
} 


int 
main(int argc, char **argv) 
{ 
     signal(SIGHUP, huphandler); 

     int i; 
     int wait = 0; 
     char *args[argc+3]; 
     args[0] = "mypy.py"; 
     for (i=0; i<argc; i++) { 
       if (argv[i][0] == 'w') { // Here's where the problem is 
         memmove(argv[i], argv[i]+1, strlen(argv[i])); 
         wait = strtol(argv[i], NULL, 10); 
       } 
       else { 
         args[i+1] = argv[i]; 
         printf("%s\n", args[i+1]); 
       } 
     } 
     argc = i + 2; 
     FILE *file; 
     Py_SetProgramName(args[0]); 
     Py_Initialize(); 
     PySys_SetArgv(argc, args); 

     while (true) { 
       defer_signal++; 
       file = fopen(strcat(getenv("HOME"), "/mypy.py"), "r"); 
       PyRun_SimpleFile(file, "mypy.py"); 
       Py_Finalize(); 
       defer_signal--; 
       if (defer_signal == 0 && signal_pending != 0) 
         exit(0); 
       if (wait > 0) sleep(wait); 
       else exit(0); 
     } 
} 
+0

你为什么试图将argv [i]的值改为1(并试图写出可能(几乎肯定是)只读内存)而不是仅仅增加argv [i]? –

+0

是的,我已将它更改为'argv [i] ++;'。我只是不确定。但它仍然失败。 – user193661

+1

发布的代码缺少声明:'#include ',这是'strtol()'和'memmove()'和'strlen()'和'strcat()'函数需要的。发布的代码缺少以下语句:'exit()'和'getenv()'函数需要'#include ' – user3629249

回答

4

我很怀疑,这个问题是存在的,这

fopen(strcat(getenv("HOME"), "/mypy.py"), "r"); 

,另一方面是非常非常错误的。

标准者禁用修改由getenv() 返回的指针,而不是你应该使用一个临时缓冲区,这应该这样做

FILE *file; 
char path[PATH_MAX]; // Include <limits.h> 
int result; 
const char *home; 
home = getenv("HOME"); 
if (home == NULL) 
    return EXIT_FAILURE; // Problem, `HOME' env variable not found? 
result = snprintf(path, sizeof(path), "%s/mypy.py", home); 
if ((result < 0) || (result >= (ssize_t) sizeof(path)) 
    return EXIT_FAILURE' // Very unlikely to happen, BUT CHECK PLEASE. 
file = fopen(path, "r") 
if (file == NULL) // Please always check ... 
    return EXIT_FAILURE; 

这将可能导致未定义行为,这意味着,你可以期望一个给定的行为,所以你不能指望程序的其他部分正常工作。


标准解释的问题摘录。

7.22.4.6的getenv功能

  • getenv函数返回一个指针,以与匹配的列表成员相关联的字符串。指向的字符串不得由程序修改,但可能会被随后对getenv函数的调用覆盖。如果找不到指定的名称,则返回空指针。
  • 该帖是从C11标准草案N1570,我强调了大胆的一部分,以使其清楚,它说,你不能修改指针。