简体   繁体   English

有人可以告诉我为什么我会在这个简单的C程序中出错吗?

[英]Can some tell me why I am seg faulting in this simple C program?

I keep on getting seg faulted after I end my first for loop, and for the life of me I don't why. 在我结束第一次循环后,我继续遇到段故障,对于我的生活,我不知道为什么。 The file I'm scanning is just 18 strings in 18 lines. 我正在扫描的文件只有18行中的18个字符串。 I thinks the problem is the way I'm mallocing the double pointer called picks, but I don't know exactly why. 我认为问题是我正在使用名为picks的双指针的方式,但我不确切知道为什么。 I'm am only trying to scanf strings that are less than 15 chars long, so I don't see the problem. 我只是试图扫描长度小于15个字符的字符串,所以我没有看到问题。 Can someone please help. 有人可以请帮助。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LENGTH 100

int main( int argc,char *argv[] )
{

   char* string = malloc( 15*sizeof(char) );
   char** picks = malloc(15*sizeof(char*));
   FILE* pick_file = fopen( argv[l], "r" );
   int num_picks;


   for( num_picks=0 ; fgets( string, MAX_LENGTH, pick_file ) != NULL ; num_picks++ )
     {
       scanf( "%s", picks+num_picks );
     }
   //this is where i seg fault
   int x;
   for(x=0; x<num_picks;x++)
     printf("s\n", picks+x);
}

picks is a pointer-to-a-pointer: that means that the things it points to, are themselves pointers. picks是一个指向指针的指针:这意味着它指向的东西本身就是指针。

When you do this: 当你这样做:

char** picks = malloc(15*sizeof(char*));

You are making picks point to a block of 15 pointers - which is fine as far as it goes (although, since you want to read in 18 lines, you really need 18 here instead of 15). 你正在picks指向一个15个指针的区块 - 尽管它很好(但是,因为你想读18行,你真的需要18个而不是15个)。 This means that picks points to a block of variables in memory like this: 这意味着picks指向内存中的变量块,如下所示:

| picks (char **) | --------> | picks[0] (char *)  | ----> ?
                              | picks[1] (char *)  | ----> ?
                              | picks[2] (char *)  | ----> ?
                              | ...                |
                              | picks[14] (char *) | ----> ?

As you can see, those 15 char * pointers are now unintialised - they don't point to anything. 正如你所看到的那样,那15个char *指针现在都没有被发现 - 它们并没有指向任何东西。 You can't start using them until you allocate some memory for those, too - you need to do something like this: 在为这些人分配一些内存之前,你不能开始使用它们 - 你需要做这样的事情:

int i;
for (i = 0; i < 15; i++)
{
    picks[i] = malloc(15);
}

Now , after that, the memory layout looks like this: 现在 ,之后,内存布局如下所示:

| picks (char **) | --------> | picks[0] (char *)  | ----> | picks[0][0] (char)  |
                                                           | picks[0][1] (char)  |
                                                           | ...                 |
                                                           | picks[0][14] (char) |

                              | picks[1] (char *)  | ----> | picks[1][0] (char)  |
                                                           | ...                 |

                              | ...                |

...and you now have places to store all those characters you want to read. ...现在你有了存放你想要阅读的所有角色的地方。

  1. string is only getting allocated enough memory to store one character ( sizeof(char) ). string只分配足够的内存来存储一个字符( sizeof(char) )。 If you want to store more characters, you'll need to multiply sizeof(char) by the size of the string you want to store, plus one for the null at the end. 如果要存储更多字符,则需要将sizeof(char)乘以要存储的字符串的大小,再加上一个用于结尾处的null。

  2. Instead of: 代替:

     char** picks = malloc(15*sizeof(char)); 

    You want to do this: 你想这样做:

     char** picks = malloc(15*sizeof(char*)); 

    Each element of the picks array needs to be big enough to hold a pointer. picks数组的每个元素都需要足够大以容纳指针。

First of all, in C strings are stored as byte (char) arrays, and have to be allocated. 首先,在C字符串中存储为byte(char)数组,并且必须进行分配。 In this situation, the string used to read he file should be allocated for MAX_LENGTH+1 (+1 for the string terminator, \\0) chars: 在这种情况下,用于读取文件的字符串应分配给MAX_LENGTH + 1(字符串终止符为+1,\\ 0)字符:

char* string = malloc( (MAX_LENGTH+1) * sizeof(char) );

This will allocate enough memory for a string of maximum length: MAX_LENGTH. 这将为最大长度的字符串分配足够的内存:MAX_LENGTH。

Another problem is that the array of pointers char **picks is not allocated to store the 18 strings you're expecting to read: 另一个问题是指针char **picks数组没有被分配来存储你期望读取的18个字符串:

It has to be allocated for 15 char pointers (char *), which also have to be allocated in the first loop. 它必须分配给15个char指针(char *),它们也必须在第一个循环中分配。

int main( int argc,char *argv[] )
{
   ...
   char* string = malloc( (MAX_LENGTH+1) * sizeof(char) );
   char** picks = malloc(15*sizeof(char *));
   FILE* pick_file = fopen( argv[l], "r" );
   int num_picks;

   for( num_picks=0 ; fgets( string, MAX_LENGTH, pick_file ) != NULL ; num_picks++ )
     {
       printf("pick a/an %s ", string );
       //--- allocate the char array to store the current string
       picks[num_picks] = malloc (15 * sizeof(char));
       sscanf(string, "%s", picks[num_picks] );
     }

   for(int x=0; x<num_picks;x++)
     printf("%s\n", picks[x]);
}

You also have to test malloc() return value, and you may want to test if the file content really is as expected and does not contain more lines, or lines longer than 15 chars. 您还必须测试malloc()返回值,并且您可能希望测试文件内容是否真的符合预期,并且不包含更多行或超过15个字符的行。


Also scanf() reads the standard input, I replaced it with sscanf(), and added the missing '%' sign in the second printf(). scanf()读取标准输入,我用sscanf()替换它,并在第二个printf()中添加缺少的'%'符号。

  • The location pointed to by string is only allocated space for one char, but you try to read up to MAX_LENGTH chars into it; string指向的位置仅为一个 char分配空间,但是您尝试将MAX_LENGTH字符读入其中;
  • The location pointed to by picks is only allocated space for 15 char * pointers, but you apparently want to store pointers to 18 strings there; picks指向的位置只为15个char *指针分配空间,但你显然想存储指向18个字符串的指针;
  • The location pointed to by picks is allocated but never initialised. picks指向的位置已分配但从未初始化。 You need to make those 15 (or 18) pointers actually point to something themselves, before you hand them to scanf . 在将它们交给scanf之前,你需要让那些15(或18)个指针实际指向某些东西。

In this case, there is actually no need for dynamic allocation at all - you could do what you want with arrays: 在这种情况下,实际上根本不需要动态分配 - 你可以用数组做你想做的事情:

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

#define MAX_LENGTH 100
#define MAX_LINES 18

int main(int argc, char *argv[])
{
    char string[MAX_LENGTH];
    char picks[MAX_LINES][MAX_LENGTH];
    FILE *pick_file = NULL;
    int num_picks;

    if (argc > 1)
        pick_file = fopen(argv[1], "r");

    if (pick_file == NULL)
        return 1;

    for (num_picks = 0; num_picks < MAX_LINES && fgets(string, MAX_LENGTH, pick_file) != NULL; num_picks++)
    {
        printf("pick a/an %s ", string);
        scanf("%s", picks[num_picks]);
    }

    int x;
    for (x = 0; x < num_picks; x++)
        printf("%s\n", picks[x]);

    return 0;
}

Is it because in the line: 是因为在线:
for( num_picks=0 ; fgets( string, MAX_LENGTH, pick_file ) != NULL ; num_picks++ )
MAX_LENGTH is 100 but you're reading into the variable string , which can only hold an individual character? MAX_LENGTH是100,但是你正在读取变量string ,它只能容纳一个单独的字符?

You are allocating an array of fifteen char* for picks : 你正在为picks分配一个十五个char*的数组:

char** picks = malloc(15*sizeof(char*));

Now picks has enough space to store fifteen char* , but you never actually put any pointers inside that would point to memory that should contain the read characters. 现在picks有足够的空间来存储十五个char* ,但是你实际上从未在内部放置指向应该包含读取字符的内存的指针。

You need to allocate memory for these strings that will be read with scanf . 您需要为将使用scanf读取的这些字符串分配内存。 At the moment scanf just writes the data to wherever the pointers in picks (that have not been initialized to point anywhere useful) are pointing to. 目前, scanf只是将数据写入picks的指针(尚未初始化为指向任何有用的位置)指向的位置。

ur getting seg fault here. 你在这里得到段故障。

scanf( "%s", picks+num_picks );

instead do this, 而是这样做,

for( num_picks=0 ; fgets( string, MAX_LENGTH, pick_file ) != NULL ; num_picks++ )
 {
   pics[num_picks] = (char* )malloc(100);
   scanf( "%s", picks+num_picks );
 }

The problem is, u allocated **pics to hold 15 strings, but u read the strings without allocating the space for those strings. 问题是,你分配**pics来保存15个字符串,但你读取字符串而不为这些字符串分配空间。 make sure u always read into allocated pointers. 确保你总是读入已分配的指针。

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

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