Live data from Hacker News

*(char*)0 = 0; – What does the C++ programmer intend with this code? [video]

youtube.com

21–30 of 199 posts

Re: *(char*)0 = 0; – What does the C++ programmer intend with this code? [video]

#21
Old school comment... back in the day, there were computers on which dereferencing the null pointer would in fact return zero. And given that a typical linked list is terminated by a null, mistakes could creep in where "points to a 0" was checked when "pointer is 0" should have been. Needless to say, code like this would crash in mysterious ways when compiled on a machine where location 0, while readable, had nonzero contents. The alternative, getting a segfault because 0 wasn't mapped, is preferable because then you see the problem right away.

Anyhow it's just barely possible that this assignment was a hack to make this sort of code work on a machine where address 0 is (uninitialized) nonzero and can be harmlessly made zero.

Re: *(char*)0 = 0; – What does the C++ programmer intend with this code? [video]

#23

This statement would be technically legal on its own in x86 real mode if the compiler didn't do null pointer checks. However it would set the divide-by-zero IRQ handler to itself 0000:0000, and when the next division by zero happened, the machine run into UB (likely a reset or halt) because it would jump there, do 4x ADD byte ptr [BX + SI], AL (or ADD byte ptr [EAX], AL) followed by running the remaining interrupt ve…

If I'm understanding what you're saying correctly, the memory location with address 0 is actually a writable address, but with the value being used semantically to handle division by zero? It's kind of wild to me that would even something that's even allowed to be done manually, let alone required by a certain mode. Is this something provided for compatibility reasons that you'd have to opt into, or is it just something enabled by default?

Re: *(char*)0 = 0; – What does the C++ programmer intend with this code? [video]

#25
When I see that code my head immediately translates to "store a byte with value 0 at memory address zero". 0 the integer needs to be cast to a char * to treat it as a byte address (rather than a word) and the * means "assign to the memory location given by the pointer.

I would probably use something like this when hacking on an Apple II with a zero page.

I have also written programs that ran on VMS which dumped memory starting at '0' without getting any segfaults.

Re: *(char*)0 = 0; – What does the C++ programmer intend with this code? [video]

#26
post #23

This statement would be technically legal on its own in x86 real mode if the compiler didn't do null pointer checks. However it would set the divide-by-zero IRQ handler to itself 0000:0000, and when the next division by zero happened, the machine run into UB (likely a reset or halt) because it would jump there, do 4x ADD byte ptr [BX + SI], AL (or ADD byte ptr [EAX], AL) followed by running the remaining interrupt ve…

If I'm understanding what you're saying correctly, the memory location with address 0 is actually a writable address, but with the value being used semantically to handle division by zero? It's kind of wild to me that would even something that's even allowed to be done manually, let alone required by a certain mode. Is this something provided for compatibility reasons that you'd have to opt into, or is it just someth…

Back in the day there were no protections. You could write to any address whether it was used by the CPU for interrupt vectors, part of the OS, hardware addresses, anything.

Re: *(char*)0 = 0; – What does the C++ programmer intend with this code? [video]

#27
post #14

Earlier quoted context omitted.

Not quite. (char *) 0 is the null pointer. The null pointer is not necessarily a binary all-zero. On some compilers in x86, the null pointer intentionally points to something which will cause a crash when written to.

Find me one contemporary example (ANSI C) with a disassembled screenshot. This is writing sizeof(char) (== 1 almost everywhere) zero to address zero. It is not using a NULL macro or other predefined symbol. In the real world, this would generally write a byte to address 0000:0000, leading to UB because it would fuck up the divide-by-zero IV. PS: I used Borland C++ 3.1, Microsoft C++ 3.x and 4.5x, Watcom, and early GN…

It doesn't have to be the NULL macro, which is correctly defined as plain 0.

The literal 0 is treated specially, so this could indeed be one of those 'turns into a weird bit pattern NULL pointers', if such a thing existed in the wild anymore.

But you're correct in that there probably haven't been any since the turn of the century or whenever the last Univac mainframes got turned off.

Re: *(char*)0 = 0; – What does the C++ programmer intend with this code? [video]

#28
post #25

When I see that code my head immediately translates to "store a byte with value 0 at memory address zero". 0 the integer needs to be cast to a char * to treat it as a byte address (rather than a word) and the * means "assign to the memory location given by the pointer. I would probably use something like this when hacking on an Apple II with a zero page. I have also written programs that ran on VMS which dumped memor…

On ATmega processors, the register file is mapped to 0, so this would be writing 0 to r0.. which GCC reserves as a dedicated 0 register anyway.

Re: *(char*)0 = 0; – What does the C++ programmer intend with this code? [video]

#29

This statement would be technically legal on its own in x86 real mode if the compiler didn't do null pointer checks. However it would set the divide-by-zero IRQ handler to itself 0000:0000, and when the next division by zero happened, the machine run into UB (likely a reset or halt) because it would jump there, do 4x ADD byte ptr [BX + SI], AL (or ADD byte ptr [EAX], AL) followed by running the remaining interrupt ve…

Not quite, I think. Since this is a char pointer being used, only the first byte of the interrupt address would be zeroed. Since in real mode those are far pointers, the lower byte of the segment would be zeroed. So xx00:xxxx.

But yes, the interrupt table was my first thought when reading the headline.

Re: *(char*)0 = 0; – What does the C++ programmer intend with this code? [video]

#30

Before I watch the full talk for the answer (what I've seen so far, he states there's not a right answer)... I know on some microcontrollers (e.g. Arm) addresses 0x0 and 0x4 are usually used to define the initial stack pointer and entry point and then are never needed again. Later, you probably want to detect the presence of null pointers by checking if &maybeAStruct is either 0 or valid. If you accidentally test the…

This is C code. Coder needs specifity hwo to align the char pointer to HW alignment expectations for memory address to prevent a segmentation fault.

Char pointers have alignment 1 on any conforming implementation and all pointers are aligned at 0. The code will write to "address 0", assuming the compiler hasn't freaked out because (char*)0 is the char null pointer and thus undefined behavior to access. Note the additional caveat that address 0 may not be the first 8 bits of mapped memory (which isn't necessarily addressable).
Post reply on HN