*char 数组末尾的分段错误
Segmentation fault at the end of a *char array
我是 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)
来自 strtok() 手册
RETURN VALUE
The strtok() and strtok_r() functions return a pointer to the next
token, or NULL if there are no more tokens.
一旦没有更多的标记,token
包含一个 NULL 指针,因此 strlen(token)
段错误。参见 strlen not checking for NULL
你的程序有问题:你对日期组件的索引,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] = '[=10=]';
}
/* 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 语言的新手,运行 遇到了问题。我想使用以下代码将来自 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)
来自 strtok() 手册
RETURN VALUE The strtok() and strtok_r() functions return a pointer to the next token, or NULL if there are no more tokens.
一旦没有更多的标记,token
包含一个 NULL 指针,因此 strlen(token)
段错误。参见 strlen not checking for NULL
你的程序有问题:你对日期组件的索引,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] = '[=10=]';
}
/* 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()
.