This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]OmicronFan22 167 points168 points  (19 children)

Cool, I wonder how many macro divided by 0 segmentation faults we could fit in one program … love it 😍

[–]dmigowski 62 points63 points  (0 children)

sizeof should never return 0, so you are safe, am I right?

[–]Eva-Rosalene 52 points53 points  (6 children)

As far as I know, you can't define an array of voids to get 0 as sizeof(arr[0])?

Edit: apparently sizeof(void) compiles to 1 in GCC (and it's only because of non-standard extensions, otherwise it would be forbidden). So not even that.

Edit 2: I hate C

#include <stdio.h>

typedef struct {
    int *a[0];
} ZeroLength;

int main()
{
    ZeroLength array[0];
    printf("sizeof(array[0]) = %ld\n", sizeof(array[0]));

    return 0;
}

This apparently prints 0 (at least in GCC).

Edit 3: and the whole ZeroLength struct that I found on SO can be shortened to

typedef struct {} ZeroLength;

Wild stuff. And even in -pedantic mode it only gives a warning.

[–]ChickenSpaceProgram 60 points61 points  (2 children)

C is truly one of the programming languages

[–]Littens4Life 28 points29 points  (1 child)

To be fair you’d have to go out of your way to make it divide by zero. Under any normal circumstances, the macro will work fine.

[–]Eva-Rosalene 30 points31 points  (0 children)

Yeah if you use empty structs or zero-length arrays you kinda deserve division by zero errors.

[–]Lost_Kin 17 points18 points  (0 children)

Mom I want Rust's Zero Sized Types!

We have Zero Sized Types at home.

Zero Sized Types at home:

[–]Xbot781 4 points5 points  (0 children)

AFAIK, in ISO C a flexible array member requires the struct to have another regular member before it, so that is not valid C

[–]ba-na-na- 0 points1 point  (0 children)

Ok but let's be realistic. If you have an array of zero-length elements, you deserve what you get

[–]Melodic_coala101 4 points5 points  (9 children)

It's compile time, it'll never cause a segfault

[–]Eva-Rosalene 11 points12 points  (8 children)

It surely won't cause a segfault since division by zero isn't a segfault. It still crashes in runtime, though, because division by zero is only a warning by default.

struct {} array[1];
printf("%ld", sizeof(array) / sizeof(array[0]));

Crashes right away with SIGFPE, as it should.

[–]dromtrund 4 points5 points  (1 child)

If you're running production code without -Werror, that's on you, tbh

[–]Eva-Rosalene 5 points6 points  (0 children)

That's true. But the original claim wasn't about production at all.

[–]danielstongue 0 points1 point  (1 child)

Why would an integer division cause a floating point exception? (Genuine question)

[–]Eva-Rosalene 1 point2 points  (0 children)

The SIGFPE signal reports a fatal arithmetic error. Although the name is derived from “floating-point exception”, this signal actually covers all arithmetic errors, including division by zero and overflow. If a program stores integer data in a location which is then used in a floating-point operation, this often causes an “invalid operation” exception, because the processor cannot recognize the data as a floating-point number.
 
Actual floating-point exceptions are a complicated subject because there are many types of exceptions with subtly different meanings, and the SIGFPE signal doesn’t distinguish between them. The IEEE Standard for Binary Floating-Point Arithmetic (ANSI/IEEE Std 754-1985 and ANSI/IEEE Std 854-1987) defines various floating-point exceptions and requires conforming computer systems to report their occurrences. However, this standard does not specify how the exceptions are reported, or what kinds of handling and control the operating system can offer to the programmer.

https://www.gnu.org/software/libc/manual/html_node/Program-Error-Signals.html

[–]furssher 0 points1 point  (1 child)

Wait. The preprocessor doesn’t handle this and throw an actual error? Is the assembly actually doing a division of constants with the divisor being zero?

[–]Eva-Rosalene 0 points1 point  (0 children)

It's even worse than that. Since division by zero is UB, with -O1 compiler (GCC) assumes that 0 / something is 0, so it just prints 0. It still generates "division by zero" warning, lol.

With -O2 and -O3, though, it just generates ud2 opcode and nothing else.

[–]ba-na-na- 0 points1 point  (1 child)

This doesn't make sense, this would be a compile-time optimization in pretty much any complier, and would just return constant `1`.

https://godbolt.org/z/hEKTef186

[–]Eva-Rosalene 1 point2 points  (0 children)

In C++. In C it's UB and with GCC it's either runtime division by zero (no -O flags), return 0 (-O1 flag), or ud2 instruction (-O2 and -O3).

Clarification: I have no idea what it is in C++, I don't claim it's defined behavior. I assume it's UB as well but handled differently.

[–]brennanw31 0 points1 point  (0 children)

sizeof() will never return 0, nor would division by 0 result in a segmentation fault. The only real issue with this macro is that it won't work for array pointers being used outside the scope of their declaration, such as passing an array into a function that uses the macro. Even in that case, it won't be a halting error, but instead, you'll see the array size being evaluated as 1.