[英]strptime throws Segmentation fault when passing char array to const char *
当我尝试将 char 数组传递给 const char * 时出现分段错误
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
static char *
get_valid_date_format(const char *date) {
struct tm result;
char *ret;
char **f;
char *formats[] = {"%Y", "%Y-%m", "%y-%m", "%Y-%m-%d", "%y-%m-%d",
"%Y%m%d", "%y%m%d", "%Y-%m-%d %T", "%y-%m-%d %T", "%Y%m%d%H%M%S",
"%y%m%d%H%M%S", "%Y-%m-%dT%T", "%y-%m-%dT%T", "%Y-%m-%dT%TZ",
"%y-%m-%dT%TZ", "%Y-%m-%d %TZ", "%y-%m-%d %TZ", "%Y%m%dT%TZ",
"%y%m%dT%TZ", "%Y%m%d %TZ", "%y%m%d %TZ", NULL };
memset(&result, 0, sizeof(result));
for (f = formats; f && *f; f++)
{
printf("check format: %s\n", *f);
ret = strptime(date, *f, &result);
if (ret && *ret == '\0')
{
printf("found Format: %s\n\n", *f);
return *f;
}
}
return (char *)0;
}
void main()
{
char *format;
char *date = "2020-07-25T00:10:58";
char date2[] = "2020-07-25T00:10:58";
char *date3 = "2020-07-25T00:10:58.000Z";
date2[3] = '1';
format = get_valid_date_format(date2);
if (format == NULL) {
printf("format is NULL\n");
return;
} else {
printf("format found = %s\n", format);
}
}
如果我调用 get_valid_date_format(date),那么它工作正常。 所以用 char * 调用可以找到,但是当传递 char[] 时,我会遇到分段错误。 我需要使用数组,因为我需要在调用 get_valid_date_format 之前对其进行修改。
正如M. Nejat Aydin 评论的那样, strptime
不是标准 C function,它来自 BSD,是 Z6EC1BD1EA6A5D67A63B20C8F14Z 使用的 POSIX 标准的一部分。 为确保已加载,请添加-D_XOPEN_SOURCE=700
以加载 X/Open 和 POSIX 扩展。
编译器警告会告诉您许多其他潜在问题。 如果您使用的是 gcc 或 clang 等命令行编译器,则必须运行编译器警告。 有很多选择,我推荐-Wall -Wshadow -Wwrite-strings -Wextra -Wconversion -std=c11 -pedantic
。
char *formats[]
声明 function 本地的char *
数组。 您正在返回其中一个元素。 通常返回局部变量会导致 memory 错误,因为 memory 可以在 function 退出时释放。 但formats
由未释放的字符串文字组成。 但是您错误地将它们声明为可写char *
。 您可以 go 从非常量到常量,但您不能 go 从常量到非常量。
formats
应该是const char *formats[]
,一个只读数组const char *
。 它们是只读字符串文字,永远不会被释放(静态),可以从 function 安全地返回。 对于腰带和吊带,声明formats
static
因为它只需要分配一次。
同样, get_valid_date_format
应该返回static const char *
, format
应该是const char *
,并且f
是一个const char **
。
尽管某些编译器允许void main
,但这是无效的。 main
返回一个int
。
char *foo = "...";
是不正确的。 它是一个char foo[] = "..."
或一个const char *foo
如果它是只读的。 这适用于所有日期变量。 const char *date =...
, const char *date3 = "..."
并且因为您修改了date2
, char date2[] =...
。
无需检查f
在循环中是否为真,只需*f
,但它不会受到伤害。
return (char *)0;
最好写成return NULL;
无需使用memset
初始化result
,因为您只是将它传递给strptime
,它将用自己的值覆盖。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.