简体   繁体   English

* char数组末尾的分段错误

[英]Segmentation fault at the end of a *char array

I'm new to using C and I'm running into a problem. 我是使用C的新手,但遇到了问题。 I want to use the following code to split-up a string input from the linux command line (something like date | ./date_split ) into an array, which I will be later accessing and modifying. 我想使用以下代码将来自linux命令行的字符串输入(例如date | ./date_split )拆分为一个数组,稍后将对其进行访问和修改。 The splitting works initially but I get a segmentation fault at the end. 分割最初起作用,但最后出现分割错误。 Can anyone explain what I am doing wrong? 谁能解释我在做什么错?

int main()
{
   char *indate[10];
   int i= 1;
   char str[100][50];
   fgets(&str [0], 50, stdin);
   const char s[2] = " ";
   char *token;

  /* get the first token */
  token = strtok(str, s);
  indate[i] = malloc(strlen(token)+1);
  strcpy(indate[i], token);
  printf( "Array before: %s\n", indate[i]);     

 /* walk through other tokens */
 while( token != NULL )
{
  printf( "Token before: %s\n", token );

  token = strtok(NULL, s);
  indate[i] = malloc(strlen(token)+1);
  strcpy(indate[i], token);

printf( "Token2 After: %s\n", token );
printf( "Array2 After: %s\n", indate[i]);     
i++;   
}

    return(0);
}

Which gives terminal output: 给出终端输出:

Array before: Thu
Token before: Thu
Token2 After: 20
Array2 After: 20
Token before: 20
Token2 After: Oct
Array2 After: Oct
Token before: Oct
Token2 After: 11:37:56
Array2 After: 11:37:56
Token before: 11:37:56
Token2 After: EDT
Array2 After: EDT
Token before: EDT
Token2 After: 2016

Array2 After: 2016

Token before: 2016

Segmentation fault (core dumped)

Issues with your program: your index into the date components, i , starts at 1 instead of 0 (is a terrible variable name for this purpose) and isn't updated consistently (first entry gets overwritten); 程序问题:日期成分i索引从1开始而不是0(为此目的是一个糟糕的变量名),并且更新不一致(第一个条目被覆盖); the str() array is a total mess allocation-wise (eg two dimensions, only one used); str()数组是总的混乱分配方式(例如,二维,仅使用一个); you assume the first strtok() succeeds but that might not be the case with bad input; 您假设第一个strtok()成功,但是输入错误可能不是这种情况; you don't test if the subsequent strtok() calls succeed until after you've already used the result; 您必须先使用结果,然后才能测试随后的strtok()调用是否成功; you make no attempt to free() the memory you malloc() and even lose track of some. 您不会尝试free() malloc()的内存,甚至会丢失一些内存。

Below is a rework of your original code that also adds some error checking and other niceties: 以下是对原始代码的重做,还添加了一些错误检查和其他优点:

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

#define MAXIMUM_TOKENS 16
#define MAXIMUM_TOKEN_LENGTH 32

const char *separator = " ";

int main()
{
    char string[(MAXIMUM_TOKEN_LENGTH + strlen(separator)) * MAXIMUM_TOKENS + 1]; // estimate

    char *result = fgets(string, sizeof(string), stdin);

    if (result == NULL)
    {
        fprintf(stderr, "An appropriate error message goes here.\n");
        return EXIT_FAILURE;
    }

    /* strip final newline (\n) if present */
    size_t last_index = strlen(string) - 1;

    if (string[last_index] == '\n')
    {
        string[last_index] = '\0';
    }

    /* get the first token */
    char *token = strtok(string, separator);

    char *date_parts[MAXIMUM_TOKENS];
    int date_parts_index = 0;

    /* walk through other tokens */
    while (token != NULL)
    {
        date_parts[date_parts_index++] = strdup(token);
        token = strtok(NULL, separator);
    }

    /* print the tokens and free the strdup/malloc memory */
    for (int i = 0; i < date_parts_index; i++)
    {
        (void) puts(date_parts[i]);
        free(date_parts[i]);
    }

    return EXIT_SUCCESS;
}

USAGE 用法

% date | ./a.out
Thu
Oct
20
09:58:00
PDT
2016
% 

Although this is an appropriate use of strtok() , be wary of it. 尽管这是strtok()的适当用法,但请注意。 It is an artifact of an earlier age and should be avoided in favor of safer, modern library functions like strsep() and strtok_r() . 它是较早的人工strsep() ,应避免使用更安全,现代的库函数,例如strsep()strtok_r()

From strtok() manual 从strtok()手册

RETURN VALUE The strtok() and strtok_r() functions return a pointer to the next token, or NULL if there are no more tokens. 返回值strtok()和strtok_r()函数返回指向下一个标记的指针,如果没有更多标记,则返回NULL。

Once there are no more tokens, token contains a NULL pointer, and therefore strlen(token) seg faults. 一旦没有更多令牌, token包含NULL指针,因此出现strlen(token)段错误。 See strlen not checking for NULL 请参阅strlen不检查NULL

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

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