#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 : %x\n",start_addr,stop_addr,offset);
  printf("\n Permission : %s\n",access);
  printf("\n Filename : %s\n",filename);
    return 0;
}

On Linux this gives the correct output but on Solaris the file is called libdl.so (there is no libdl.so.0 on Solaris) so I wonder what makes this difference, there is not this file on Solaris and if I change to the filename of the Solaris installation (libdl.so) then it generates a segmentation fault.

$ 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

The above is on ubuntu and here is on Solaris where it compiles without warnings but generates a segmentation fault:

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

Update

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:~>
有帮助吗?

解决方案

Check the man page for Solaris 10 sscanf. The %m modifier is not supported there.

You should also check the return value of sscanf.

其他提示

Your compiler (on Ubuntu, and probably Solaris if you enabled the warning) told you what is wrong:

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]
⋮

You need to use %llx in your printf, just like you did in your sscanf.

Passing the wrong type of argument is undefined behavior. On Linux, it happened to work (this time); on Solaris, it didn't.

[You're really asking a question about the C language and libraries, you'd probably have better luck searching Stack Overflow for answers, rather than here.]

edit: see also msw's answer, which points out another problem, at least as important as this one.

It's actually much simpler than it might look. Your code has never allocated space to store the string results into. This shorter code has the same defect:

#include <stdio.h>
int main() {
    char *word = NULL;
    sscanf("hello world", "%s", &word); 
    printf("%s\n", *word);
    return 0;
}

The reason it may "work" on one compiler but not another may have to do with how storage is allocated. Here is the error generated by that code:

cperm.c:5:5: error: format ‘%s’ expects argument of type ‘char *’, 
             but argument 3 has type ‘char **’

Which doesn't seem horrible, but it's actually fatal. Running gcc with the -Werror option would make that warning stop compilation and not create an a.out. Defining and using word properly

char word[64];
sscanf("hello world", "%63s", word); 
printf("%s\n", word);

compiles without error and works.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top