1

I'm playing with pointers in order to understand them, so i'd like to know why I can't, for example, print the value of the address 0 (zero) and others.

#include <stdio.h>
int main()
{
    int *i = 0;
    int *e = (int*)0x100;

    while (i <= e)
    {
        printf("%d\n", *i);
        i++;
    }

    return 0;
}

This example crashes.

Fabricio
  • 7,705
  • 9
  • 52
  • 87
  • I suggest that you try to initialize the pointers with the address of things (e.g `int *x=&y`), instead of assigning integer values into them. Casting integers into pointers isn't the way to use pointers. – ugoren Feb 02 '12 at 13:04
  • Trying to dereference 0 address is invalid in any case, even not touching the problem of accessing random memory addresses that possibly wasn't allocated to your process. – Andriy Tylychko Feb 02 '12 at 13:13
  • You might want to tell which system this is for. Your code is perfectly fine in some systems, but will not work in others (Windows etc). – Lundin Feb 02 '12 at 14:45
  • @ugoren That depends on which system the code is intended for. This code could be perfectly fine on some systems. – Lundin Feb 02 '12 at 14:46
  • @AndyT You can't know that without knowing which system the code is executed on. – Lundin Feb 02 '12 at 14:47
  • @Lundin, "I'm playing with pointers in order to understand them" seems to mean he's a C novice, trying to learn the basics. For this, you start with stuff like setting them to point to a variable, not with memory mapped I/O. – ugoren Feb 02 '12 at 14:56
  • @ugoren Actually, memory mapped I/O is how you do a "Hello world" program when learning C on an embedded system. The first program you write would typically lit up a LED through port I/O. – Lundin Feb 02 '12 at 15:02
  • 1
    @Lundin "Among the invalid values for dereferencing a pointer by the unary * operator are a null pointer" (footnote 102 in 6.5.3.2). That code evokes undefined behaviour, it's not fine on any system. – Daniel Fischer Feb 02 '12 at 15:04
  • @DanielFischer Yes but a null pointer isn't necessarily 0 in C. Check the [C FAQ](http://c-faq.com/null/varieties.html). They even dedicated a whole chapter to null pointers. – Lundin Feb 03 '12 at 07:29
  • @Lundin Yes, but `int *i = 0;` assigns a null pointer to `i`, not necessarily address 0. So the `printf("%d\n",*i);` is undefined behaviour. (I'm not sure whether `(int*)0 <= (int*)0x100` may legitimately evaluate to false. `if (0) undefined_behaviour;` isn't UB, iirc, so in that case the code may be fine.) – Daniel Fischer Feb 03 '12 at 09:30

6 Answers6

2

You can only dereference valid pointers. These are pointers returned from e.g. malloc(), or pointers generated by taking the address of something. Dereferencing an invalid pointer is undefined behevior.

In your case, your operating system likely doesn't allow you to read memory that isn't mapped to your process, which is why it kills the process when you try.

unwind
  • 391,730
  • 64
  • 469
  • 606
  • That's not strictly true. You can access any memory you want to (that system allows you to). You should be able to access (for example) functions binary codes and so on. – Vyktor Feb 02 '12 at 13:04
  • @Vyktor: you can access only memory that was allocated for your process. Function binary code was allocated and to access it you need to take the address of this function, as `unwind` said. – Andriy Tylychko Feb 02 '12 at 13:11
  • Ummm.... no, @Vyktor, that's simply not true. Certain addresses are off-limits. This is entirely OS- and architecture-dependent, of course, but on a UNIX-like system, this will die with a `Bus Error` message. – Ernest Friedman-Hill Feb 02 '12 at 13:11
  • @AndyT I'm sorry, I've misread unwinds answer I though he wrote that you can access only memory allocated via `malloc()`, of course you can only access memory of your process (but I think it's more general to say that it's any memory that your OS allows you to, in most cases = memory allocated to your process). – Vyktor Feb 02 '12 at 13:16
  • @Andy I think what Vyktor means by "memory that system allow you to access" is memory that was allocated for your process. – Ben Feb 02 '12 at 13:19
  • @Vyktor: most OSs allocate memory for your process, not entire 4GB (x86) at startup, but on demand, by pages. If you'll try to access unallocated address you'll receive access violation. – Andriy Tylychko Feb 02 '12 at 13:21
  • @AndyT Yep, I understand that... But few years back I've tried `while(1){ print(ptr); ptr++;}` and it just started dumping memory (On windows) and stopped just when I killed process. I guess that's not going to work anymore :). I've just tested 2 small programs (look at my answer) and all memory I got access to was memory inside loop boundaries. And yes, Ben's right. I was referring to allocated memory (but I though there're some special addresses that every application has access to, for example some system info). – Vyktor Feb 02 '12 at 13:30
  • strictly speaking in C standard words a null pointer IS a valid pointer. But a null value is an invalid value for the indirection operator. – ouah Feb 02 '12 at 13:47
  • 1
    @Vyktor: The only formally meaningful way to say memory allocated to your process is to enumerate the ways a valid pointer can be obtained. These are by `malloc`, by the address-of operator, by array-to-pointer decay, or as a return (or other result) value of a function in the standard library that yields a pointer to an object as if obtained by `malloc` or of static storage duration. (Hope I didn't miss any.) Systems may of course add other ways, such as `mmap` on POSIX. Conversion of a function pointer need not yield a valid accessible data pointer. – R.. GitHub STOP HELPING ICE Feb 02 '12 at 16:20
2

Access Violation...

You don't have access to all of your memory directly, there are protected areas.

To put it simply, an access violation occurs any time an area of memory is accessed that the program doesn't have access to.

http://blogs.technet.com/b/askperf/archive/2008/06/03/access-violation-how-dare-you.aspx

Pheonix
  • 6,049
  • 6
  • 30
  • 48
1

0 is a null pointer constant

(C99, 6.3.2.3p3 ): "An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant."

Dereferencing a null pointer is undefined behavior.

(C99, 6.5.3.2.p4) "If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined.87)"

and

87): "Among the invalid values for dereferencing a pointer by the unary * operator are a null pointer, an address inappropriately aligned for the type of object pointed to, and the address of an object after the end of its lifetime."

ouah
  • 142,963
  • 15
  • 272
  • 331
1

From C standard, paragraph 6.5.3.2/4

"If an invalid value has been assigned to the pointer, the behaviour of the unary * operator is undefined."

An example of an invalid value is the null pointer. So what you do might work and might not work. I know that on HP-UX 11.31 with gcc 4.3.1 it will work and not crash. in you case it crashes. As you see the standard does not imposes any particular behaviour in this situation.

0

You're probably trying access memory which your program isn't allowed to access and "crash" is just system preventing "virus" (you :) ) from destroying it.

Here's a little linux code compiled with gcc:

#include <stdio.h>

int b;

int main() {
    char *ptr = (char*)&b;
    ptr -= 2368;
    int i;

    for( i = 0; i < 3984; i++){
        printf( "%d: %c\n", i, ptr[i]);
    }

    printf( "\n");

    return 0;
}

If you try to access -2369 bytes you'll get segmentation fault (access violation). If you try to access more than 3984th byte (3983th including "zero byte") you'll get the same error (this is probably page size usable for application use).

You can also access binary code directly:

char *ptr = (char*)&main;
ptr -= 999;
int i;

for( i = 0; i < 3763; i++){
    printf( "%c", ptr[i]);
}

On my system is address of b: 0x600970

And address of main: 0x4004e4

So you can see you have access to different scopes of memory, but you're limited just to those.

Vyktor
  • 20,559
  • 6
  • 64
  • 96
0

Not all the addresses in the address space are mapped to an actual memory cell on a physical memory module. When you try to read the value at address NULL (i.e. the cell at address 0) that is not mapped to anything, your system detects it and kills your process with a segmentation falt signal or something similar.

Ben
  • 7,372
  • 8
  • 38
  • 46
  • 1
    Address 0 isn't necessarily a NULL pointer. See [this](http://stackoverflow.com/questions/5142251/redefining-null). – Lundin Feb 02 '12 at 14:49
  • 2
    @Lundin But 0 is a _null pointer constant_, it need not indicate address 0, but that's a different matter. – Daniel Fischer Feb 02 '12 at 15:09