简体   繁体   English

数组和指针的分段错误

[英]Segmentation fault with arrays and pointers

I have a segmentation fault...i'm not sure what's causing it. 我有细分错误...我不确定是什么原因造成的。 Also, when passing the member pname into the function get_names, am I doing this correctly, or is there a better way of doing this? 另外,将成员pname传递给函数get_names时,我是否正确执行此操作,或者有更好的方法吗?

#include <stdio.h>

#define MAX_NAME 20
#define MAX_PLAYRS 16

typedef struct {
    char pname[MAX_NAME];
    int runs;
    char how_out;
} Team_t;

Team_t player[MAX_PLAYRS];
Team_t *player_ptr[MAX_PLAYRS];
void get_names (int count, char *str);

int main (void) {
    int i;
    for (i = 0; i < MAX_PLAYRS; i++) {
        get_names(i, &(*player[i].pname));
        printf("Player: %s\n", player[i].pname);
    }
}

void get_names (int count, char *str) {
    FILE *inp;
    char status;

    inp = fopen("teamnames.rtf", "r");
    status = fscanf(inp, "%s", str);
    if (status == EOF) {
        count = MAX_PLAYRS;
    }
}

With your code unchanged, I get a segmentation fault if the file can't be opened properly (ie it's unreadable due to permissions, or it simply does not exist). 在您的代码不变的情况下,如果无法正确打开文件(例如,由于权限而无法读取,或者根本不存在),则会出现分段错误。

Here's a modified version of you function get_names() : 这是您的函数get_names()的修改版本:

void get_names(int count, char *str)
{
  FILE *inp;

  inp = fopen("teamnames.rtf", "r");

  if (inp == NULL) {
    perror("Failed");
    return;
  }

  fgets(str, MAX_NAME, inp);

  fclose(inp);
}

This would still read the first name 16 times, but it would tell you why it didn't manage to open the file. 该名称仍会读取16次,但会告诉您为什么它无法打开文件。 To read the next name from the file (rather than repeatedly the first name), open (and close) the file in the main() function instead. 要从文件中读取名字(而不是重复名字),请改为在main()函数中打开(并关闭)文件。

Also, you might as well call get_names() like so: 另外,您get_names()好像这样调用get_names()

get_names(i, player[i].pname);

No need to do that &(*...) thing you're doing. 不需要做您正在做的&(*...)

And, finally, I hope that the teamnames.rtf file is not actually an RTF file, but a simple text file with a name on each line. 最后,我希望teamnames.rtf文件实际上不是RTF文件,而是每行都有名称的简单文本文件。

Get a debugger to tell you what is wrong. 让调试器告诉您出了什么问题。 Compile the code with debugging enabled (see you man page for your compiler) and run something like this: 在启用调试的情况下编译代码(请参见您的编译器手册页),然后运行以下命令:

gdb a.out core

Then you should be able to see which line made the code core dump. 然后,您应该能够看到哪一行进行了代码核心转储。 You could use idb as well, if you have the intle compiler installed. 如果已安装intle编译器,则也可以使用idb。 This is, of course, on *nix. 当然,这是在* nix上。 If you are talking windows, use the VS debugger. 如果您正在使用Windows,请使用VS调试器。

In addition do NOT use fscanf as it is unsafe. 此外, 请勿使用fscanf因为它不安全。 Use fgets instead. 请改用fgets

The problem comes from this line: 问题来自此行:

get_names(i, &(*player[i].pname));

Understanding pointers and dereferencing is one of the biggest adjustments to learning C if you are switching from another language. 如果要从另一种语言切换,那么了解指针和取消引用是对学习C的最大调整之一。 You're doing it wrong, and I think you should seek out a tutorial on the subject. 您做错了,我认为您应该寻找关于该主题的教程。 Try http://www.cplusplus.com/doc/tutorial/pointers/ as a starting point. 尝试以http://www.cplusplus.com/doc/tutorial/pointers/作为起点。

There are many strange things. 有很多奇怪的事情。 First thing is, it seems like the names are in a file, but what you are doing is in every iteration of your for loop, you call get_names which opens the file again, that is goes to the beginning of the file and you read the same name over and over again. 第一件事是,名称似乎在文件中,但是您正在做的是在for循环的每次迭代中,您调用get_names再次打开文件,即转到文件的开头,然后阅读一遍又一遍的同名。

That is if you closed the file. 那就是如果您关闭文件。 Since you haven't closed the file, the file is already open and you keep reopening it (which could be the cause of your problem) 由于您尚未关闭文件,因此该文件已经打开并且您一直在重新打开它(这可能是导致问题的原因)

Another thing is, how can 另一件事是,如何

if (status == EOF) {
    count = MAX_PLAYRS;
}

Give you the current count? 给你当前的数目? Regardless of the count of the players in the file, you are just setting it to MAX_PLAYERS . 无论文件中有MAX_PLAYERS播放器,您都将其设置为MAX_PLAYERS

Another thing is that count is an input to the function that is not a pointer, so setting it does not change the value outside the function (which is what I assumed you wanted). 另一件事是count是函数的输入,而不是指针,因此设置它不会更改函数外部的值(这是我假设您要的值)。

Here is how I would do it with minimum change to your code: 这是我将对您的代码进行最小更改的方式:

#include <stdio.h>

#define MAX_NAME 20
#define MAX_PLAYRS 16

typedef struct {
    char pname[MAX_NAME];
    int runs;
    char how_out;
} Team_t;

Team_t player[MAX_PLAYRS];
Team_t *player_ptr[MAX_PLAYRS];
void get_names (int count, char *str, FILE *inp);

int main (void) {
    FILE *inp;
    int i;
    int count;
    inp = fopen("teamnames.rtf", "r");
    for (i = 0; i < MAX_PLAYRS; i++) {
        get_names(&count, player[i].pname, inp);
        printf("Player: %s\n", player[i].pname);
    }
}

void get_names (int *count, char *str) {
    char status;

    status = fscanf(inp, "%s", str);
    if (status == EOF) {
        *count = MAX_PLAYRS;
    }
}

Here is how I would do it more concisely: 这是我将更简洁地执行的操作:

#include <stdio.h>

#define MAX_NAME 20
#define MAX_PLAYRS 16

typedef struct {
    char pname[MAX_NAME];
    int runs;
    char how_out;
} Team_t;

Team_t player[MAX_PLAYRS];
Team_t *player_ptr[MAX_PLAYRS];
int get_names (Team_t *team);

int main (void) {
    get_names(player);
}

int get_names (Team_t *team) {
    int i = 0;
    FILE *inp;
    inp = fopen("teamnames.rtf", "r");
    while (i < MAX_PLAYRS && !feof(inp) {
        fscanf(inp, "%s", team[i].pname);
        printf("Player: %s\n", player[i].pname);
    }
}

Note that the problems with fscanf , checking array boundaries etc are not the concern of this solution, but this rather gives you the idea of what to do not a code for you to copy-paste. 注意fscanf ,检查数组边界等不是此解决方案的问题,而是使您了解了什么不需要复制粘贴代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM