In a linux program code ,I use "mmap"to mmap something to the memory, but it runs errorly,,I use gdb totry to find the problem ,I find when I use mmap function, I make its parameter "NULL",so the system can automatically get the start address ,but I find the address 0xb7d90000 <Address 0xb7d90000 out of bounds>!
what can I do to slove the problem?

This is wrong. Never cast a pointer to int. On amd64, an int is smaller than a pointer, so you lose precision. Checking the value for less than zero is also wrong. In a 3/1 split, user programs can receive mappings that are less than zero and not an error. You should, as noted in the man page, compare the result to the symbolic constant MAP_FAILED.

lxjhjx wrote:

Code:

{
printf("mmap failed!\n");
perror("mmap");

This is wrong. Calling printf can change the value of errno, in which case perror will print the wrong value. This is why your output says that mmap failed with Success.

You can check that with a debugging printf() of mbuf.size
after the above ioctl() call and before calling mmap() to see what
mbuf.size is initialized to before passing it to mmap().

There may not really be an error here. You ran it in gdb because
your code was reporting an mmap() error that perror() does not find
an errno for. gdb is reporting the address returned by mmap() as
out-of-bounds, but that may be some misperception by gdb
that happens with MAP_SHARED. Or maybe the initialization of
mbuf.size to a sane value is not happening before calling mmap().
Whatever.

Fix the error check after mmap() and then see if it still reports
an mmap() error._________________TIA

What the others said about MAP_FAILED, and errno changing: if you want to do anything besides simply print it, use an int e; if (some call failed) { e = errno; perror("some func"); if (e == EINVAL) .. } and so on, then you can restore errno = e before you return a failure value like NULL, or just return -e if your function returns a non-negative signed integral for success. perror is defined in POSIX not to change errno, but istr this was only made explicit recently, so as with using other system functions, I think it's best to stick to the one pattern, which is saving errno as soon as something goes wrong. (You might be using some other function like fprintf with strerror, or not even be on a Unix system, so better to get into the habit from the get-go.)

This is also more performant on modern systems, since errno is not a simple int, but eg *(errno_func) where int *errno_func(void) returns thread errno location. So accessing errno is not as simple as accessing the traditional extern int errno, which was never as simple as a conventional int in any case, and none of those are as simple as checking a local automatic. And as you've seen, errno can and will change as soon as you call some other function.

Additionally, you shouldn't cast the return value from mmap: in C, void * pointers can be assigned to (or from) any other pointer type. This usually shows up as casting the return value from malloc. This is not a good idea, as if you've forgotten to include the correct header, C will assume the function returns an int, which you then cast to a pointer (Hu already explained why that's a bad idea.) Linkage will work, since the symbol is usually in libc, but it will blow up at runtime (or not, depending on the machine: making it the kind of bug that really p*sses people off, since the package will still build, and the warnings will be lost in a build log somewhere.)

C++ requires the cast, so you sometimes see people recommend them to make code work if compiled with C++. If this is a concern, it's a much better idea to use macros for it (you already need them for extern "C" { in any event, and of course you'll be changing Standard C header names, right? ;)

Code:

if ((void *) buf == MAP_FAILED)

This is so nearly right, I feel bad for pointing out the portability aspects. Firstly, there's no need to cast buf to a void * since char * and void * are specified to be the same underlying type in C (they can both point to any object), and in C++ all pointers have the same base type. As a pattern, though this seems correct (eg if buf is an int *, there's no guarantee in C that it has the same size as a void * or char *) equality operators are defined to cast it to a void * if being compared with a void * (which is what MAP_FAILED should be):

C99 Sec 6.5.9, para 5 1256.pdf wrote:

If one operand is a pointer and the other is a null pointer constant, the null pointer constant is converted to the type of the pointer.
If one operand is a pointer to an object or incomplete type and the other is a pointer to a qualified or unqualified version of void, the former is converted to the type of the latter.

On some systems however, MAP_FAILED is not defined to be a pointer at all, believe it or not, so to be safe you should cast that instead:

Code:

if (buf == (void *)MAP_FAILED)

I can't remember which system uses plain: -1 instead of: (void *)-1 as the definition; I read about it a couple of months ago (I have to code portably for work.) It was something like AIX or HP-UX, before a particular version, one of those old ones that some people like to mock, but others respect. In any event, why worry about it, when you can make your code work everywhere that has mmap?

Additionally, you shouldn't cast the return value from mmap: in C, void * pointers can be assigned to (or from) any other pointer type. This usually shows up as casting the return value from malloc. This is not a good idea, as if you've forgotten to include the correct header, C will assume the function returns an int, which you then cast to a pointer (Hu already explained why that's a bad idea.) Linkage will work, since the symbol is usually in libc, but it will blow up at runtime (or not, depending on the machine: making it the kind of bug that really p*sses people off, since the package will still build, and the warnings will be lost in a build log somewhere.)

C++ requires the cast, so you sometimes see people recommend them to make code work if compiled with C++. If this is a concern, it's a much better idea to use macros for it (you already need them for extern "C" { in any event, and of course you'll be changing Standard C header names, right?

C++ requires the function to be properly declared, so it is guaranteed to be a compilation error to use mmap in a C++ source file without including the proper header. C can guess linkage in some cases, though as steveL points out, this is more likely to cause problems than to avoid them. C++ cannot guess linkage, because it needs to know the types for proper name mangling. For unmangled functions, like standard C library functions, it needs an extern "C" declaration to tell it not to mangle the name.

If the right compiler flags are used, a straight C program can be made to fail to compile if declarations are missing. For any new code, I highly recommend this, since it avoids the problems steveL describes above. I like to start with -Werror -Wall -Wextra, which catches many, but not all, problems. Those problems which are caught are converted to hard errors. Distributors dislike packages which use -Werror, so you may want to include a build time flag that they can use to skip the -Werror, while keeping the other flags.

This is wrong. Never cast a pointer to int. On amd64, an int is smaller than a pointer, so you lose precision. Checking the value for less than zero is also wrong. In a 3/1 split, user programs can receive mappings that are less than zero and not an error. You should, as noted in the man page, compare the result to the symbolic constant MAP_FAILED.

lxjhjx wrote:

Code:

{
printf("mmap failed!\n");
perror("mmap");

This is wrong. Calling printf can change the value of errno, in which case perror will print the wrong value. This is why your output says that mmap failed with Success.

You can check that with a debugging printf() of mbuf.size
after the above ioctl() call and before calling mmap() to see what
mbuf.size is initialized to before passing it to mmap().

There may not really be an error here. You ran it in gdb because
your code was reporting an mmap() error that perror() does not find
an errno for. gdb is reporting the address returned by mmap() as
out-of-bounds, but that may be some misperception by gdb
that happens with MAP_SHARED. Or maybe the initialization of
mbuf.size to a sane value is not happening before calling mmap().
Whatever.

Fix the error check after mmap() and then see if it still reports
an mmap() error.

I fix the "mmap" problem ,but got a new problem ,I list the problem in the last reply,help me ...........

First change: open() returns -1 on error, so you only need to test
that fd is less than 0 to see if there was an open() error.

Second change: the cast of buf (declared as char *) is unneeded,
because MAP_FAILED is defined to be void * (in /usr/include/sys/mman.h
on Gentoo), and C rules force buf to be evaluated as void *, too,
when testing with "==" against another void *.

Does the JPG file already exist? If so, what is its mode (what are its
permissions)? What are the permissions of the /home/lxj/ directory?

fopen() can fail on malloc() errors, too (it allocates a buffer for
a FILE * behind the scenes), if you have reached the memory
limit on your system or for your user, if the internal malloc()
tables in your process have been corrupted by some previous
bug, and so on. One thing you can try is to simply open() the JPG
file first, getting a file descriptor for it, then fdopen(), using that
returned file descriptor as an argument to fdopen(), to get a FILE *.

That would tell you whether you can open() that JPG
pathname at all.

(For a safer alternative to perror(), see libiberty's xstrerror() in the
binutils or gcc sources.)_________________TIA