Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

Can your C compiler do this:

Name: Anonymous 2010-05-15 15:06


int main()
{
  int *p;
  p  = 0;
  *p = 0;
  return 0;
}


?

Name: Anonymous 2010-05-15 15:07

Almost got me there 3/10

Name: Anonymous 2010-05-15 15:09

And no. ANSI guaranties a pointer will never validly equal 0

Name: Anonymous 2010-05-15 15:16

>>1
Yes, it generates the reasonable code(on x86):

C705 00000000 00000000    MOV DWORD PTR DS:[0],0
33C0                      XOR EAX,EAX
C3                        RETN

>>3
If it's true, it's a stupid requirement. On most architectures there can be something on address 0.

Name: Anonymous 2010-05-15 15:54

So what's under the zero memory address?

Name: Anonymous 2010-05-15 16:00


$ cat > main.c << EOF
int main()
{
  int *p;
  p  = 0;
  *p = 0;
  return 0;
}
EOF
$ gcc main.c -o main
$ ./main
Segmentation fault


I expected it. I also use Linux

Name: Anonymous 2010-05-15 16:04

>>6

Fuck you nerd

Name: Anonymous 2010-05-15 16:08

>>6
Of course, same would happen in most OSes.
>>5
There's no negative addresses of course.
So if you subtracted 1 from the 0 pointer, you'd get -1, or treated as an unsigned int: 0xFFFFFFFF (on 32bit).

Name: Anonymous 2010-05-15 16:14

>>7
>Calls me a nerd
>Browses /prog/
[sup]HA[sub]HA[sup]HA[sub]HA[sup]HA[sub]HA[sup]HA[sub]HA[sup]HA[sub]HA[sup]HAHA[sup][/sub][sup][/sub][sup][/sub][sup][/sub][sup][/sub][sup]

Name: Anonymous 2010-05-15 16:24

>>9
i call you a failure, now gtfo and take your ugly wtf code with you!

Name: Anonymous 2010-05-15 16:40

>>4
That's nonsense. Most architectures guarantee that you can't access 0 specifically to give you a value for nurupo.
There are exceptions, but not many.

Name: Anonymous 2010-05-15 16:45

>>8
True.
So, OP's question is badly formulated.
Rather, the question is, "Can your operating system do this?".

Name: Anonymous 2010-05-15 16:53

>>11
How can they do that?

On x86, if you're in real mode or in ring0 in protected mode, you can access it just fine. It points to the interrupt table. 0+ is 256 element array containing each interrupt handler's address/descriptor (IDT). The structure of each element is a bit different in protected mode than is in real mode.

In real mode, if you dereferenced 0, you would get the address of the first interrupt handler.

Of course, most people run their applications in user mode, and there's nothing at address 0 in user-mode (a few pages from 0 are reserved by the OS for safety purposes), but you could put something there if you wanted to (using some hacks), or you could emulate that something is there using exception handlers (costly).

So at least on x86, address 0 is a perfectly valid address, altough it can be reserved for special purposes, so you'll segfault/access violation if you tried to access it, at least unless an exception handler decided to emulate that something is at address 0.

The situation is similar on non-x86 arch's, and if you want address 0 to be reserved, it will usually depend on the writers of the OS, or in rarer cases on the CPU designers.

What lies at address 0 is absolutely platform-specific and if the platform designers decide to please C coders, they may decide to reserve that space to prevent coding errors, but nothing gurantees that there won't be anything at address 0.

Name: Anonymous 2010-05-15 17:23

>>11
Back in the day, most platforms actually put zero at address zero, so that a null pointer was equivalent to the empty string. Apparently, converting all this code to use a real empty string on platforms with memory protection was a mess.

Name: Anonymous 2010-05-15 17:28

>>14
It's not hard to emulate that behaviour using an exception handler(VEH,SEH, hook on KiUserExceptionDispatcher, interrupt 0xE hook in ring 0, or anything inbetween that code)  on Win32 at least. Pretty sure you can do it on *nix too, but through different mechanisms.

But, why would you want errors to go unnoticed?

Name: Anonymous 2010-05-15 19:27

>>11

|
|⌒彡
|冫、)  / ̄ ̄ ̄ ̄ ̄
|` / <   ぬるぽ?
| /    \_____
|/
|

Name: Anonymous 2010-05-15 21:44


$ cat 0.c
int main()
{
  int *p;
  p  = 0;
  *p = 0;
  return 0;
}
$ cc 0.c
$ ./a.out
Access violation at 00001000


Zero page is reserved for the process information block and is read-only in usermode.

Name: Anonymous 2010-05-16 0:10

>>15
They weren't errors. That's kindof the point. Dereferencing a null pointer was well defined and supported on these platforms. Obviously using an exception handler to work around it in a modern OS is a horrible idea.

Name: Anonymous 2010-05-16 0:20

>>18
Why is it a horrible idea?
It would certainly be fixed to a CPU and an OS, but it's most certainly doable.

On Win32, I'd make a SEH or VEH handler which catches access violations (EXCEPTION_ACCESS_VIOLATION), then I would access the ExceptionInformation field of the EXCEPTION_RECORD structure and see what the address is. If the address is 0, I would have to use a disassembler(or hardcode the disassembly if it's simple enough) and check what the instruction at EIP is. Depending on the instruction, it would do the things it expected you to do (dereferencing with writing would get the exception passed up, if it's just reading, return a pointer to some nulls, so you'd get your empty string).

As you can see, this behaviour is perfectly achievable, but obtaining it is very platform specific.

Name: Anonymous 2010-05-16 0:45

>>18
No, it is not. Dereferencing null pointer is bad. And everyone knows it.

Name: Anonymous 2010-05-16 0:52

>>1
any program (it doesn't even have to be a C compiler) can do that.
it's behavior when given that program is completely compliant with the C standard, no matter what program it is.

Name: Anonymous 2010-05-16 0:55

>>14,18
if a zero address is a valid address, then a null pointer doesn't point to the zero address. iso c specifically says that a null pointer doesn't point to a valid address.

Name: Anonymous 2010-05-16 0:59

null is not always 0 faggots. 0 is valid on some obscure fucktarded architectures.

Name: Anonymous 2010-05-16 1:13

>>22
That doesn't sound quite right to me. Can you provide a citation?

Name: Anonymous 2010-05-16 1:26

>>22
Then most archs disregard that rule:
- A pointer is almost always represented using an integer value (or similar), sized the same as the size of the machine's registers.
- Usually, any address(which is the size of an integer) can be valid under certain circumstances on most archs.
- NULL is commonly equal to 0, and 0 may or may not be reserved by the OS for safety purposes, but even in those cases that it's reserved, it's usually possible to emulate that something exists at that address (same is true for any address).

Given those things, that means that as long as a pointer is stored as an unsigned int on a specific arch, that rule can be broken in practice. Reserving an address can make things slightly safer. Even if 0 wasn't reserved, you could for example reserve/alloc a small block of memory at a certain address, call that NULL, and set the access flags to that page to prohibit all access(read/write/execute/...), which would give the same results. Of course, someone could subvert or change that behaviour making whatever the address of NULL is a valid address, thus as long as a pointer is represented internally as an unsigned int, then it will be possible to break that ISO C rule(if it exists).

The real solution is to use another bit besides the pointer to mark validity. Be it a tag bit, or a more strange arch with tag bits, or something of that sort. Of course, since C is a low-level language which is usually used for efficiency reasons, something like that won't happen unless the CPU supports it natively.

There are always some minor differences and disregarded restrictions between a language definition and a language implementation, that's especially the case for low-level languages like C which are pretty close to the metal. When it comes to more high-level languages, the standards tend to be followed much more to the letter (except when there are errors in the standard...).

Name: Anonymous 2010-05-16 1:36

>>19
It's a bad idea because it would be SLOW.

>>20,22
This is pre-standardization, guys. C wasn't standardized until 1989.

Name: Anonymous 2010-05-16 1:38

>>26
Exceptions aren't as slow as you'd think, but they're reasonably costly (let's say 10k cycles on average, but it totally depends on the individual handlers). How often do you think people would dereference NULL? Whenever it happens on modern OS'es, it's almost always an error, so the cost is justified.

Name: Anonymous 2010-05-16 1:39

>>24
6.3.2.3, paragraph 3, from the c standard:
If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.

Name: Anonymous 2010-05-16 1:41

>>26
ah, so it's sepples shit. i should have known.

Name: Anonymous 2010-05-16 2:17

>>28
Oh, that is a bit different... the spec doesn't say "valid address" but instead talks about extant "objects" and "functions".

I know it sounds really pedantic, but quite a few systems I've worked on actually do have 0 as a valid address, with C compilers still using 0 for null. Most of the time no objects were put there, however.

Name: Anonymous 2010-05-16 2:45

>>30
if it can't have an object or function in it, it's not a valid address. if it can, then there has to be some value for a pointer to it that compares unequal to a null pointer.

Name: Anonymous 2010-05-16 3:43

>>27
Jesus christ, are you paying attention to the topic? I said people USED to use a null pointer as the empty string before modern virtual memory and the standardization of C, and it was a bitch to fix. You said they could just use exception handling as a workaround instead of fixing it. I said that would be too slow. Then you say:

Whenever it happens on modern OS'es, it's almost always an error, so the cost is justified.
No shit sherlock. Did you miss the part where I agree with you?

This whole thread has felt like arguing with a bunch of goldfish. I'm done here.

Name: Anonymous 2010-05-16 3:57

>>32
So angry...

You didn't use a namefield to say who you are and this board doesn't have an id system anymore(that's fine). I don't keep track of posters, unless their identities are obvious.

Name: Anonymous 2010-05-16 3:58

>>32
>I'm done here.
Ragequit liek FV?

Name: Anonymous 2010-05-16 4:37

>>31
The problem is that we have different ideas of what constitutes a valid address, and you should note that the spec uses careful language. (I really don't like your definition for reasons I don't care to get into and I have a feeling that's what is being reflected in the spec.)

I have noticed, however:
if it can, then there has to be some value for a pointer to it that compares unequal to a null pointer.
It's not too uncommon for memory contents to start at some block and repeat at regular intervals, that is: accesses to addresses within a certain range are effectively modulo some constant. This can leave 0x00000000 as 'valid' while still providing objects there at unequal locations. (If it runs the whole address space, it also poses serious problems for coming up with an invalid address anywhere. However, according to the spec, there are still options--such as never providing pointers to extant objects at those locations.)

Name: Anonymous 2010-05-16 4:45

>>35
The only way to solve this is to have typed objects. null/nil could be such an object. Something like that can be done effectively by using tag bits on each object, but then it would hardly be C anymore. If pointers are effectively unsigned integers and any unsigned integer can be potentially a valid address under the right circumstances then it's impossible to truly satisfy that ISO C requirement. That's the case for most C compilers on x86, but it doesn't have to be the case for x86_64 (you don't really need to use the whole address space = few people have that much RAM or paging files) and it's not on archs with the addresses being smaller than the registers(a pointer can be tagged. Lisp Machines did it that way and some older archs did it too, but that's not say it's the most efficient way to do things, as type checks in hardware can be costly, and they change the whole arch around).

Name: Anonymous 2010-05-16 5:02

>>36
The only way to solve this is to have typed objects.
That's not true at all. If you want to insist that it is, please do provide a citation from the spec.

Name: Anonymous 2010-05-16 5:25

>>37
How else would you solve it if any unsigned int can be a valid pointer, and the internal representation of a pointer is an unsigned int? There's simply not enough bits to store the information to store that a pointer is invalid or null. You could reserve a special address to be null, but that has its drawbacks, and in some cases may even be unfeasible.

Name: Anonymous 2010-05-16 5:40

>>38
I'd solve it by realizing that obtaining an invalid address is not a requirement: see the last statement in >>35. There is no problem. Unless you are simply taking the goal of obtaining an invalid address, in which case I misunderstood your comment--but then it has no bearing on standards conformance that I know of.

Name: >>38 2010-05-16 5:44

Altough, I guess if you reserve the memory area represented by NULL (be it a valid address containing real data, or not), then nothing else could be using it, so as long as the user checks if memory allocation functions return NULL, then the allocation has failed. One could use page protection to make reads/writes to it fail as well, but it's not possible on all archs. This way, even if there's some real data at *NULL, it would be the user's fault for dereferencing it, as by convention NULL shouldn't be a pointer the user should access normally (the convention would only be broken during the initial setup of the pointer, which could be done by the OS or the C runtime). Some errors might be unnoticed, but it might fit the needed definition.

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List