我几乎成功修改了一个公开可用的程序。如果我从它自己的目录运行它,它可以正常工作:
$ 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行开始。感谢所有的评论和给予的帮助!