测试字符串中的第一个字符会给出分段错

时间:2016-02-01 15:46:42

标签: c

我正在尝试给我的程序一个命令行参数,删除第一个字符并将剩余的字符串转换为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);
        }
}

1 个答案:

答案 0 :(得分:4)

我非常怀疑问题存在,这个

fopen(strcat(getenv("HOME"), "/mypy.py"), "r");
另一方面,

非常非常错误。

标准禁止修改getenv() 1 返回的指针,而应该使用临时缓冲区,这应该这样做

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;

这可能会导致未定义的行为,这意味着您不能指望给定的行为,因此您无法期望程序的其余部分正常工作。

1 摘自解释问题的标准

  

7.22.4.6 getenv功能

     
      
  1. getenv函数返回指向与匹配列表成员关联的字符串的指针。指向的字符串不应被程序修改,但可能会被后续调用getenv函数覆盖。如果找不到指定的名称,则返回空指针。
  2.   

引用来自C11标准草案N1570,我强调了粗体部分,以便明确说明你无法修改指针。