#include <stdio.h>
int main() {
char *str = "11111111-22222222 r-xp 00000000 00:0e 1843624 /lib/libdl.so.0";
unsigned long long start_addr, stop_addr, offset;
char* access = NULL;
char* filename = NULL;
sscanf(str, "%llx-%llx %m[-rwxp] %llx %*[:0-9a-f] %*d %ms",
&start_addr, &stop_addr, &access, &offset, &filename);
printf("n start : %x, stop : %x, offset : %xn",start_addr,stop_addr,offset);
printf("n Permission : %sn",access);
printf("n Filename : %sn",filename);
return 0;
}
在Linux上给出正确的输出,但在Solaris上该文件被称为libdl。所以没有libdl.so。所以我想知道是什么造成了这种差异,Solaris上没有这个文件,如果我更改为Solaris安装的文件名(libdl.so),那么它会产生分段错误。
$ cc Cperm.c ;./a.out
Cperm.c: I funktion "main":
Cperm.c:11:3: varning: format "%x" förväntar sig argument av typen "unsigned int", men argument 2 har typen "long long unsigned int" [-Wformat]
Cperm.c:11:3: varning: format "%x" förväntar sig argument av typen "unsigned int", men argument 3 har typen "long long unsigned int" [-Wformat]
Cperm.c:11:3: varning: format "%x" förväntar sig argument av typen "unsigned int", men argument 4 har typen "long long unsigned int" [-Wformat]
start : 11111111, stop : 22222222, offset : 0
Permission : r-xp
Filename : /lib/libdl.so.0
上面是ubuntu上的,下面是Solaris上的,它编译时没有警告,但会产生一个分段错误:
uname -a
SunOS 5.10 Generic_148888-03 sun4u sparc SUNW,Ultra-4
my:~>cc Cperm.c;./a.out
start : 0, stop : 11111111, offset : 0
Segmentation fault
更新my:~>uname -a;gcc -Wall Cperm.c
SunOS 5.10 Generic_148888-03 sun4u sparc SUNW,Ultra-4
Cperm.c: In function `main':
Cperm.c:9: warning: unknown conversion type character `m' in format
Cperm.c:9: warning: long long unsigned int format, pointer arg (arg 5)
Cperm.c:9: warning: unknown conversion type character `m' in format
Cperm.c:9: warning: too many arguments for format
Cperm.c:11: warning: unsigned int format, different type arg (arg 2)
Cperm.c:11: warning: unsigned int format, different type arg (arg 3)
Cperm.c:11: warning: unsigned int format, different type arg (arg 4)
my:~>gcc Cperm.c
my:~>
查看Solaris 10 sscanf
的手册。此处不支持%m
修饰符
您还应该检查sscanf
的返回值
您的编译器(在Ubuntu上,如果您启用了警告,可能还有Solaris)告诉您哪里出错了:
Cperm.c:11:3: varning: format "%x" förväntar sig argument av typen "unsigned int", men argument 2 har typen "long long unsigned int" [-Wformat]
⋮
您需要在printf
中使用%llx
,就像您在sscanf
中所做的那样。
传递错误类型的参数是未定义的行为。在Linux上,它碰巧工作了(这次);
[如果你真的在问一个关于C语言和库的问题,你可能会在Stack Overflow中找到答案,而不是在这里。]
edit:参见msw的回答,它指出了另一个问题,至少和这个问题一样重要。
实际上比看起来简单得多。您的代码从未分配空间来存储字符串结果。这个较短的代码有相同的缺陷:
#include <stdio.h>
int main() {
char *word = NULL;
sscanf("hello world", "%s", &word);
printf("%sn", *word);
return 0;
}
它可能在一个编译器上"工作"而在另一个编译器上不工作的原因可能与如何分配存储有关。下面是该代码生成的错误:
cperm.c:5:5: error: format ‘%s’ expects argument of type ‘char *’,
but argument 3 has type ‘char **’
这看起来并不可怕,但实际上是致命的。带-Werror选项运行gcc将使该警告停止编译,而不是创建a.out
。正确定义和使用word
char word[64];
sscanf("hello world", "%63s", word);
printf("%sn", word);