c - *char 数组末尾的段错误

标签 c arrays linux segmentation-fault memory-segmentation

我是 C 语言的新手,但遇到了一个问题。我想使用以下代码将来自 linux 命令行的字符串输入(类似于 date | ./date_split)拆分为一个数组,稍后我将访问和修改它。拆分最初有效,但最后出现段错误。谁能解释我做错了什么?

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

给出终端输出:

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)

最佳答案

您的程序存在问题:您对日期组件的索引 i 从 1 而不是 0 开始(对于此目的来说这是一个糟糕的变量名称)并且更新不一致(第一个条目获取覆盖); str() 数组在分配方面一团糟(例如,二维,只使用了一个);您假设第一个 strtok() 成功,但输入错误可能并非如此;在您已经使用结果之前,您不会测试后续的 strtok() 调用是否成功;你没有尝试 free()malloc() 的内存,甚至忘记了一些内存。

下面是对您的原始代码的返工,其中还添加了一些错误检查和其他细节:

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

用法

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

虽然这是对 strtok() 的适当使用,但要小心。它是早期的产物,应该避免使用更安全、现代的库函数,如 strsep()strtok_r()

关于c - *char 数组末尾的段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40159117/

相关文章:

从头复制到找到的最后一个匹配项

linux - 如何使用可加载模块修改Linux网络堆栈?

linux - 将 32 位程序转换为 16 位程序

c - 进程ID,waitpid

c - 查找元素是否在指定数组中

php - 如何从数组中删除键并更新索引?

javascript - php 数组中转换 json 字符串时出现问题

c - 在另一个函数 : Segmentation fault (core dumped) 中使用 strcat

c - libc 创建/访问哪些匿名区域?

linux - 编译后添加 -fvisibility=hidden