尝试打印指针结构的某些部分时出现分段错误

时间:2014-02-16 03:17:42

标签: struct fault

我正在编写一个程序,必须使用用户输入来为结构的某些部分赋值。我需要创建一个指向结构的指针,我将通过它作为一个唯一的参数,用于单独打印结构的每个部分的函数。我还必须为结构使用malloc内存。就像现在一样,程序编译并运行main并询问用户输入。在收集最后一个用户输入之后以及当我假设运行对printContents函数的调用时,会发生分段错误。任何帮助将不胜感激!

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

struct info
{
        char name[100], type;
        int size;
        long int stamp;
};

void printContents(struct info *iptr);

int main(void)
{
        struct info *ptr=malloc(sizeof(struct info));

                printf("Enter the type: \n");
                scanf("%c", &(*ptr).type);
                printf("Enter the filename: \n");
                scanf("%s", (*ptr).name);
                printf("Enter the access time: \n");
                scanf("%d", &(*ptr).stamp);
                printf("Enter the size: \n");
                scanf("%d", &(*ptr).size);

        printf("%c", (*ptr).type);

        printContents(ptr);

}

void printContents(struct info *iptr)
{

        printf("Filename %s Size %d Type[%s] Accessed @ %d \n", (*iptr).name, (*iptr).size, (*iptr).type, (*iptr).stamp);

}

3 个答案:

答案 0 :(得分:0)

ptr-&gt;成员就像访问结构变量吧? scanf()usr&amp; ptr-&gt;成员也可以获得相同的值。对于char输入,仅使用ptr-> charmember。

答案 1 :(得分:0)

检查运营商优先顺序。这是&(*ptr).type你要做的事情吗?也许&((*ptr).type)

答案 2 :(得分:0)

首先让我们这么做。我们假设代码已经编写,编译器告诉我们什么没用,我们没有调试器。首先我们输入一些诊断输出语句,我们发现崩溃发生在printContents

printf("testing four\n"); /* we see this, so the program gets this far */
printf("Filename %s Size %d Type[%s] Accessed @ %d \n", (*iptr).name, (*iptr).size, (*iptr).type, (*iptr).stamp);
printf("testing five\n"); /* the program crashes before this */

如果我们仍然看不到错误,我们通过准备minimal compete example来缩小问题范围。 (这是一项非常有价值的技能。)我们一遍又一遍地编译和运行代码,对事情进行评论。当我们发表评论并且代码仍然是段错误时,我们会完全删除它;但如果将其评论出来会导致问题消失,我们将其重新放入。最终我们得到了一个最小的案例:

#include <stdio.h>

int main(void)
{
  char type;

  type = 'a';

  printf("Type[%s]\n", type);
}

现在应该很明显:当我们printf("%s", x)某事时,printf期望x成为字符串。也就是说,x应该是指向以空字符结尾的字符数组的第一个元素(即地址)的指针。相反,我们给它一个字符(在这种情况下为'a'),它将其解释为数字(在本例中为97),并尝试在内存中转到该地址并开始读取; 我们很幸运没有比segfault更糟糕的事情。修复很容易:决定type应该是char还是char[],如果它是{ {1}}然后将char语句更改为“%c”,如果它是printf,则更改其声明。

现在这是一个简单的方法。如果我们使用像gcc这样的好编译器,它会警告我们我们正在做一些可疑的事情:

char[]

将来,您可以通过某种方式为自己省去所有这些麻烦。得到一个神秘的错误和回溯,而不是编写大量的代码,你可以以较小的增量编写。如果您一次在gcc foo.c -o foo foo.c:35: warning: format ‘%s’ expects type ‘char *’, but argument 4 has type ‘int’ 语句中添加了一个术语,那么您可能会看到错误何时出现以及哪个术语应该归咎于此。

请记住:从小而简单开始,一次添加一点复杂性,在每一步测试,永远不会添加到不起作用的代码。