Is "sizeof new int;" undefined behavior?
Asked Answered
H

2

32

code:

#include<iostream>

using namespace std;

int main() 
{
    size_t i = sizeof new int;

    cout<<i;
}

In GCC compiler, working fine without any warning or error and printed output 8.

But, in clang compiler, I got the following warning:

warning: expression with side effects has no effect in an unevaluated context [-Wunevaluated-expression]
    size_t i = sizeof new int;
  • Which one is true?
  • Is sizeof new int; undefined behavior?
Hiltner answered 3/10, 2018 at 10:1 Comment(5)
I see nothing wrong. This warning is more of a reminder, everything is well defined here.Spae
This question is related to the C counterpart Why does sizeof(x++) not increment x?, but it is a bit clearer in C++.Stith
@BartekBanachewicz - a closer equivalent in C would be sizeof malloc(some_value) which would not call malloc() and, if performed after #include <stdlib.h>, would give a result equal to sizeof(void *).Rourke
One could argue it's compiler caring about the WTF-factor.Hulahula
Also see Does not evaluating the expression to which sizeof is applied make it legal to dereference a null or invalid pointer inside sizeof in C++?Emmery
S
62

The warning doesn't state that it's UB; it merely says that the context of use, namely sizeof, won't trigger the side effects (which in case of new is allocating memory).

[expr.sizeof] The sizeof operator yields the number of bytes occupied by a non-potentially-overlapping object of the type of its operand. The operand is either an expression, which is an unevaluated operand ([expr.prop]), or a parenthesized type-id.

The standard also helpfully explains what that means:

[expr.context] (...) An unevaluated operand is not evaluated.

It's a fine, although a weird way to write sizeof(int*).

Stith answered 3/10, 2018 at 10:3 Comment(2)
It’s weird but it’s not that weird. The desire to use expressions rather than the type could be a case of DRY. In fact, in C it’s an established pattern for malloc and not doing so often leads to erroneous code. Literally writing sizeof new T by contrast is probably not sensible but it might come up in the context of a macro expansion.Nellynelms
It's a fine, although a weird way to write sizeof(int*). I'd add it's a possibly confusing way to write sizeof( int * ), as it's likely to be viewed as sizeof( int ).Ait
R
19

new operator returns pointer to the allocated memory. new int will return a pointer, therefore sizeof new int; will return size of a pointer. This is a valid code and there is no undefined behaviour here.

Warning is legit and only warns about the effect of side-effect on the operand and that's because operands of sizeof is not evaluated.

For example:

int i = 1;
std::cout << i << '\n';     // Prints 1
size_t size = sizeof(i++);  // i++ will not be evaluated
std::cout << i << '\n';     // Prints 1
Reinert answered 3/10, 2018 at 10:4 Comment(8)
Curiously, it's easy to make i++ be evaluated: cpp.sh/9774oLeopold
@DanM.; int[i++] will be evaluated at runtime, exception for variable length arrays. Note that c++ doesn't allow VLA but GCC and clang provide it as an extension.Reinert
yeah I know. Just a peculiar gotcha. Same with int(*)[i++] being either evaluated or not depending on the implementation.Leopold
@DanM. is that due to ambiguity in the spec, or compiler bugs? I'm inclined to suspect the latter.Benedikta
@MaxBarraclough It's unspecified behavior. "Where a size expression is part of the operand of a sizeof operator and changing the value of the size expression would not affect the result of the operator, it is unspecified whether or not the size expression is evaluated." port70.net/~nsz/c/c11/n1570.html#6.7.6.2p5Leopold
@DanM.; This rule is C specific. I do not remember if there is similar quote is there in C++ standard.Reinert
@Reinert this rule concerns VLAs. There are no VLAs in C++ standard.Leopold
@DanM.; Yes, I already said in earlier comment. VLA is provided as an extension by GCC and Clang for C++. The question about C++, not C. So better not to involve VLA to this discussion.Reinert

© 2022 - 2024 — McMap. All rights reserved.