C sscanf i386 与 x86_64 解析引用字符串的不同行为

C different behavior of sscanf i386 vs x86_64 parsing quoted string

我发现 sscanf 在 i386 机器上解析双引号字符串的奇怪行为。

我的代码:

char string[] = "\"1597821828\" \"MODIFY\" \"/fullpath/test2\"";
printf("line : %s", string);
int total;
char store_date[12] = "", store_etat_watch[24] = "", store_path[1024] = "";
printf("stores init:%s,%d , %s,%d , %s,%d \n",
       store_date, strlen(store_date),
       store_etat_watch, strlen(store_etat_watch),
       store_path, strlen(store_path));
total = sscanf(string,"%s %s %s", store_date, store_etat_watch, store_path);
printf("stores brut:%s,%d , %s,%d , %s,%d \n",
       store_date, strlen(store_date),
       store_etat_watch, strlen(store_etat_watch),
       store_path, strlen(store_path));

我在 debian arm64 上编译并执行它(这是我的 Makefile):

CC = gcc

ERROR_CFLAGS = -Wall -W -pedantic -Wextra -Werror CFLAGS = -static -g -O0 $(ERROR_FLAGS) -D_REENTRANT -DLinux LDFLAGS = $(ERROR_FLAGS)

all: sscanf_test

sscanf_test: sscanf_test.c $(CC) $(CFLAGS) sscanf_test.c -o sscanf_test .PHONY:clean

clean: rm -f sscanf_test

结果:

line : "1597821828" "MODIFY" "/fullpath/test2"

stores init:,0 , ,0 , ,0

stores brut:"1597821828",12 , "MODIFY",8 , "/fullpath/test2",17

这是我期望的结果。 然后我在ubuntu i386上编译并执行它:

结果:

line : "1597821828" "MODIFY" "fullpath/test2"

stores init:,0 , ,0 , ,0

stores brut:"1597821828""MODIFY",20 , "MODIFY",8 ,"/fullpath/test2",17

第一个字符串未正确解析。 如果字符串不以双引号开头:'no problem'.

char string[]="1597821828 \"MODIFY\" \"/fullpath/test2\"";

结果:

line : "1597821828" "MODIFY" "/fullpath/test2"

stores init:,0 , ,0 , ,0

stores brut:1597821828,10 , "MODIFY",8 , "/fullpath/test2",17

我必须解析以双引号开头的字符串。

有人可以帮助我吗?

char store_date[12] 太小,无法存储 字符串 *1597821828*(为清楚起见,将引号字符替换为 *。)。结果:未定义的行为 (UB)。长度为12的字符串至少需要12+1char。 +1 用于 空字符 .

它似乎在某些系统上工作对 UB 来说是正常的; UB 不是“必须失败”,而是“任何事情 都可能发生”。如果您踩到 store_data[12] 之外的内存碰巧不是编译器用于函数后面所需的任何东西,它可能会起作用。这就是使未定义的行为如此讨厌的原因:测试不能总是揭示它。


使目标数组足够大并使用 "%s" 的宽度。

// char store_date[12]="";
// total=sscanf(string,"%s",store_date);

char store_date[12+1]="";
total=sscanf(string,"%12s",store_date);

Mis-matched 说明符与 strlen()

// printf("%d \n",strlen(store_path));
printf("%zu\n",strlen(store_path));