C 分配给作为结构成员的指针会导致分段错误

C 分配给作为结构成员的指针会导致分段错误,c,segmentation-fault,c99,C,Segmentation Fault,C99,我的目标是以这样一种方式进行修改,即它需要额外的参数,该参数明确指定哪些VCS显示状态。以下是这些变化的要点: typedef struct { int debug; char *format; /* e.g. "[%b%u%m]" */ int show_branch; /* show current branch? */ int show_revision;

我的目标是以这样一种方式进行修改,即它需要额外的参数,该参数明确指定哪些VCS显示状态。以下是这些变化的要点:

typedef struct {
    int debug;
    char *format;                       /* e.g. "[%b%u%m]" */
    int show_branch;                    /* show current branch? */
    int show_revision;                  /* show current revision? */
    int show_patch;                     /* show patch name? */
    int show_unknown;                   /* show ? if unknown files? */
    int show_modified;                  /* show + if local changes? */
    unsigned int timeout;               /* timeout in milliseconds */
    char *vcs;                          /* e.g. "git", "hg" */
} options_t;

...

options_t options = {
    .debug         = 0,
    .format        = format,
    .show_branch   = 0,
    .show_revision = 0,
    .show_unknown  = 0,
    .show_modified = 0,
    .vcs           = NULL
};

...

int opt;
while ((opt = getopt(argc, argv, "hf:dt:v:")) != -1) {
    switch (opt) {
        case 'f':
            options->format = optarg;
            break;
        case 'd':
            options->debug = 1;
            break;
        case 't':
            options->timeout = strtol(optarg, NULL, 10);
            break;
        case 'v':
            printf("%s %s", options->vcs, optarg);
            //options->vcs = optarg;
            break;
    ...
}
当我像这样调用程序时,
/vcprompt-vfoo
,printf将以下内容放在输出上:
(null)git
。如果我取消对printf下面的赋值的注释,我会得到分段错误

这可能是什么原因?在我看来,我使用
vcs
所做的工作与使用
格式所做的工作完全相同。我在64位windows上的cygwin中运行这个

编辑 这就是格式的定义

#define DEFAULT_FORMAT "[%n:%b] "
...
char *format = getenv("VCPROMPT_FORMAT");
if (format == NULL)
    format = DEFAULT_FORMAT;

您没有为指向的
格式
vcs
分配任何存储空间。实际上,它们只是指针。如果要让它们指向字符串,则需要空间来存储字符串数据本身,并为终止符('\0')留出空间。处理它的一种方法是调用选项上的
strlen()
,获取它的长度,然后使用该信息,这样您就可以使用
malloc()
分配足够大的空间来容纳完整的C字符串,然后让结构中的指针指向该内存块。

更改此选项

while ((opt = getopt(argc, argv, "hf:dt:v:")) != -1) {
    switch (opt) {
        case 'f':
            options->format = optarg;
            break;
...
对此

while ((opt = getopt(argc, argv, "hf:dt:v:")) != -1) {
    switch (opt) {
        case 'f':
            options->format = strdup(optarg);
            break;

...

这样就可以在堆上创建并分配选项的副本-对于
vcs
成员也是如此。

参考
.format=format
在哪里声明
format
以及如何声明?我想你在vcprompt中发现了一个微妙的、长期隐藏的错误!看起来1)只在添加第二个使用字符串arg的选项时发生,2)取决于本地getopt()实现。(我无法在Linux上重现您的问题。)非常确定@CyberSpock的答案是正确的。固定在。谢谢你们两个!这确实奏效了。谢谢但这仍然让我想知道为什么它适用于
格式
(作为参数传入和使用默认值时),而不适用于
vcs
。很可能是您为格式分配了一个本地地址,当该地址超出范围时,您会得到未定义的行为。