2016-02-01 99 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,我強調了大膽的一部分,以使其清楚,它說,你不能修改指針。