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

发布于 2024-08-25 23:38:52 字数 716 浏览 8 评论 0原文

在我结束第一个 for 循环后,我不断出现 seg 错误,而且我一生都不知道为什么。 我正在扫描的文件只有 18 行 18 个字符串。 我认为问题在于我分配称为 picks 的双指针的方式,但我不知道确切的原因。 我只是尝试扫描长度小于 15 个字符的字符串,所以我没有看到问题。有人可以帮忙吗?

#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);
}

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.
I thinks the problem is the way I'm mallocing the double pointer called picks, but I don't know exactly why.
I'm am only trying to scanf strings that are less than 15 chars long, so I don't see the problem. 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);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

坏尐絯 2024-09-01 23:38:52

picks 是一个指向指针的指针:这意味着它指向的东西本身就是指针。

当你这样做时:

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

你正在使 picks 指向一个由 15 个指针组成的块 - 就其本身而言,这很好(尽管如此,因为你想读取 18 行,这里确实需要 18,而不是 15)。这意味着 picks 指向内存中的一个变量块,如下所示:

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

如您所见,这 15 个 char * 指针现在未初始化 - 它们不指向任何东西。在为它们分配一些内存之前,您无法开始使用它们 - 您需要执行以下操作:

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

现在,之后,内存布局如下所示:

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

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

                              | ...                |

...现在您有地方可以存储您想要读取的所有字符。

picks is a pointer-to-a-pointer: that means that the things it points to, are themselves pointers.

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). This means that picks points to a block of variables in memory like this:

| 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. 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.

怪我闹别瞎闹 2024-09-01 23:38:52
  1. string 仅分配足够的内存来存储一个字符 (sizeof(char))。如果要存储更多字符,则需要将 sizeof(char) 乘以要存储的字符串的大小,并为末尾的 null 值加一。

  2. 而不是:

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

    您想要执行此操作:

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

    picks 数组的每个元素都需要足够大以容纳一个指针。

  1. string is only getting allocated enough memory to store one character (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.

  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.

兮子 2024-09-01 23:38:52

首先,在 C 中,字符串存储为字节(char)数组,并且必须进行分配。在这种情况下,用于读取文件的字符串应分配 MAX_LENGTH+1(+1 表示字符串终止符,\0)个字符:

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

这将为最大长度的字符串分配足够的内存:MAX_LENGTH。

另一个问题是指针数组 char **picks 没有分配来存储您期望读取的 18 个字符串:

它必须分配给 15 个字符指针 (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]);
}

您还必须测试 malloc() 返回值,并且您可能想测试文件内容是否确实符合预期并且不包含更多行或长度超过 15 个字符的行。


另外 scanf() 读取标准输入,我将其替换为 sscanf(),并在第二个 printf() 中添加了缺少的“%”符号。

First of all, in C strings are stored as byte (char) arrays, and have to be allocated. In this situation, the string used to read he file should be allocated for MAX_LENGTH+1 (+1 for the string terminator, \0) chars:

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

This will allocate enough memory for a string of maximum 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:

It has to be allocated for 15 char pointers (char *), which also have to be allocated in the first loop.

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.


Also scanf() reads the standard input, I replaced it with sscanf(), and added the missing '%' sign in the second printf().

此生挚爱伱 2024-09-01 23:38:52
  • string 指向的位置仅分配了 一个 个字符的空间,但您尝试最多读取 MAX_LENGTH 个字符;
  • picks 指向的位置只为 15 个 char * 指针分配了空间,但您显然希望在那里存储指向 18 个字符串的指针;
  • picks 指向的位置已分配但从未初始化。在将这 15 个(或 18 个)指针交给 scanf 之前,您需要使它们实际指向某些东西本身。

在这种情况下,实际上根本不需要动态分配 - 您可以使用数组执行您想要的操作:

#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;
}
  • 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;
  • 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;
  • The location pointed to by picks is allocated but never initialised. You need to make those 15 (or 18) pointers actually point to something themselves, before you hand them to scanf.

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;
}
笔落惊风雨 2024-09-01 23:38:52

是因为在该行:
for( num_picks=0 ; fgets( string, MAX_LENGTH, pick_file ) != NULL ; num_picks++ )
MAX_LENGTH 是 100,但您正在读入变量 string,它只能保存单个字符?

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?

陌生 2024-09-01 23:38:52

您正在为 picks 分配一个包含 15 个 char* 的数组:

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

现在 picks 有足够的空间来存储 15 个 char* ,但您实际上从未在其中放置任何指向应包含读取字符的内存的指针。

您需要为将使用 scanf 读取的这些字符串分配内存。目前,scanf 只是将数据写入 picks 中的指针(尚未初始化为指向任何有用的位置)所指向的位置。

You are allocating an array of fifteen char* for picks:

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.

You need to allocate memory for these strings that will be read with 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.

浮云落日 2024-09-01 23:38:52

你在这里遇到了段错误。

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

而是这样做,

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

问题是,你分配了 **pics 来容纳 15 个字符串,但你读取的字符串没有为这些字符串分配空间。确保您始终读取分配的指针。

u r 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. make sure u always read into allocated pointers.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文