在其自己的目录之外运行时编程段错误

时间:2018-01-22 09:17:27

标签: c linux

几乎成功修改了一个公开可用的程序。如果我从它自己的目录运行它,它可以正常工作:

$ pwd
/Users/elisabete/Project/temperley-keyb/keyb
$ ./key ../test/example.noteb 
Cm Cm 

但如果我更改目录(无论到哪个目录),我都会收到分段错误错误:

$ cd ..
$ keyb/key test/example.noteb 
Segmentation fault: 11 (core dumped)

使用可执行文件的完整路径显然没有影响:

$ pwd
/Users/elisabete/Project/temperley-keyb/keyb
$ /Users/elisabete/Project/temperley-keyb/keyb/key ../test/example.noteb 
Cm Cm
$ cd ..
$ /Users/elisabete/Project/temperley-keyb/keyb/key test/example.noteb 
Segmentation fault: 11 (core dumped)

程序代码本身就是这样的:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
  int z=0, b=0, c=0, s=0, j, line_no=0, i, pitch, tpc_found, npc_found, seg_beat=-1, optc=0, opterr=0;
  char *parameter_file = NULL, *input_file = NULL;
  int param_file_specified = 0;

  while ((optc = getopt (argc, argv, "p:s:")) != -1)
    switch (optc) {
      case 'p':
        parameter_file = optarg;
        param_file_specified = 1;
        break;
      case 's':
         sscanf(optarg, "%d", &seg_beat);;
         break;
      case '?':
         if (optopt == 'p')
           fprintf (stderr, "Option -%c requires an argument.\n", optopt);
        if (optopt == 's')
             fprintf (stderr, "Option -%c requires an argument.\n", optopt);
         else if (isprint (optopt))
           fprintf (stderr, "Unknown option `-%c'.\n", optopt);
         else
           fprintf (stderr,
                "Unknown option character `\\x%x'.\n", optopt);
         return 1;
       default:
         abort ();
       }

  for (j = optind; j < argc; j++)
     input_file = argv[j];

  /* Codes goes on */

使用gdb运行它会得到以下结果,但我无法做到这一点:

$ gdb -q keyb/key
Reading symbols from keyb/key...Reading symbols from /Users/elisabete/Project/temperley/source/keyb/key.dSYM/Contents/Resources/DWARF/key...done.
done.
(gdb) run ../test/extract2.noteb 
Starting program: /Users/elisabete/Project/temperley/source/keyb/key ../test/extract2.noteb
[New Thread 0x2503 of process 473]
warning: unhandled dyld version (15)

Thread 2 received signal SIGSEGV, Segmentation fault.
0x00007fff6afe2ea9 in ?? ()

我已经阅读了@mspanc在this post中所说的内容,“最初argv [0]带有一定的内存分配,包含程序名称(在大多数情况下)”,但我怀疑这是不相关的我的问题是因为使用程序目录中的完整路径,以及将程序更改为更长的名称,不会使其成为段错误。

我已经在StackOverflow中阅读了很多帖子,但找不到任何有助于解决此问题的内容,所以任何帮助都会受到赞赏!

编辑:感谢@lxop的建议,我找到了问题的根源。 main()调用一个函数来读取存储在源目录中的参数文件,因此当我从任何其他目录运行该程序时,它找不到该文件并被segfalted。然后我将注释行替换为消息和退出调用:

int read_parameter_file(char *filename, int file_specified) {
  FILE *param_stream;

  if(file_specified) {
    param_stream = fopen(filename, "r");
    if (param_stream == NULL) {
      printf("Warning: cannot open \"%s\".  Using defaults.\n", filename);
      filename = "parameters";
    }
  }
  else {
    filename = "parameters";
    param_stream = fopen(filename, "r");
    if(param_stream == NULL) {
      /* filename = "key/parameters"; */
      printf("No valid parameter file found, exiting program.\n");
      exit(EXIT_FAILURE);
    }
  }
/* ... */
}

现在至少我可以优雅地退出程序,但我仍然不知道如何处理修复默认参数文件路径的问题。我应该把它放在哪里?在Makefile中(这段代码有一个非常简单的Makefile),这样每当一个人安装它时,可以指定源的完整路径?还是其他更好的地方?

源代码现在可在this github获得,有问题的函数从main.c的第64行开始。感谢所有的评论和给予的帮助!

0 个答案:

没有答案