2

I am learning C++ using the books listed here. In particular, I read that using an uninitialized local variable of built in type is undefined behavior. Now, I came across the below given example where the user seems to be using uninitialized variables x and y. The user says:

#include <string>

template<typename T>
T num_convert(const char* s, const T) {
 return static_cast<T>(std::stoll(s));
}

int main() {
//--------------------------v---------------> is this UB because x is uninitialized?
  int x = num_convert("55", x);
//-----------------------------------v------> is this UB because y is uninitialized?
  long y = num_convert("5555555555", y);
}

In the above example, I've used arrows to highlight the points where I have doubts. In particular, I want to know that are the above two highlighted statements UB because x and y are not initialized and the user is passing those to the function by value?

wohlstad
  • 12,661
  • 10
  • 26
  • 39
Alex
  • 318
  • 1
  • 14
  • 1
    If the second parameter was used in the function that will be UB. In your case it is not, so even if the value is undefined the programe is not UB. Having a nullptr pointer is not UB, dereferencing it is, same logic with uninitilized variables – Martin Morterol Sep 08 '22 at 05:02
  • 5
    I disagree with @MartinMorterol. Using an indeterminate value in any way, even passing it to a function, is using the value and thus leads to UB. Remember: You pass the argument by *value* which means the value is copied and therefore used. If you passed it by reference or as a pointer to the variable, then that would be fine. – Some programmer dude Sep 08 '22 at 05:04
  • I say run the code through ubsan, if it doesn’t light up, it’s probably a safe bet it’s safe. – Taekahn Sep 08 '22 at 05:08
  • 2
    why do you want to pass a variable in the first place? It is unused and you simply want to convert it. Just do it like `int x = num_convert("55");` – Raildex Sep 08 '22 at 05:12
  • Turn on warnings when building: The compiler should tell you that you're *using* the variables. – Some programmer dude Sep 08 '22 at 05:12
  • The original author of that code is correct: it's a hack. Why not create a class for this and overload the conversion operators: https://godbolt.org/z/edsrrjsvr – paddy Sep 08 '22 at 05:12
  • 1
    @Raildex This is not my code. Note in my question I have clearly mentioned that this code is posted by some other user [here](https://stackoverflow.com/questions/73515132/is-there-any-generic-conversion-from-stdstring-to-numeric-type/73515190#73515190). I am just trying to understand this code for academic purposes. – Alex Sep 08 '22 at 05:13
  • @Someprogrammerdude of course you are right in principle. But to be honest since the uninitialized variable is ignored I cannot imagine a situation where this is actually causing a problem. Can you think of a concrete example where a compiler optimization will cause the program to misbehave due to the UB here ? – wohlstad Sep 08 '22 at 05:17
  • @wohlstad While the UB might not create an issue in practical terms, the [warning](https://godbolt.org/z/45MfP14nc) definitely can. If you use this in a project that treats warnings as errors, and it warns on uninitialized values, then you will have a problem. – paddy Sep 08 '22 at 05:20
  • @paddy I usually enforce "treats warnings as errors" in all my projects so it's a valid point. But I was trying to understand what kind of actual runtime problem can arise from this (due to the optimizer messing up the code due to the UB). – wohlstad Sep 08 '22 at 05:23
  • @wohlstad In a constexpr context : https://wandbox.org/permlink/zych05m1K23th7P4 even without warning as error, it wont compile (like any UB). If you change `const T` to `const T&` It not UB anymore and it compile – Martin Morterol Sep 08 '22 at 05:30
  • @Someprogrammerdude No, you should look carefully. The unused argument is/was passed by value. The user [changed their answer](https://stackoverflow.com/questions/73515132/is-there-any-generic-conversion-from-stdstring-to-numeric-type/73515190#comment130047670_73515190) by [editing](https://stackoverflow.com/posts/73515190/revisions) after i told them that the program has UB. Did you not see the [comments](https://stackoverflow.com/questions/73515132/is-there-any-generic-conversion-from-stdstring-to-numeric-type/73515190#comment130047246_73515190) below that answer? – Jason Sep 08 '22 at 06:47
  • @JasonLiam Ah, missed the editing history. Thanks for pointing it out. – Some programmer dude Sep 08 '22 at 10:10
  • @Someprogrammerdude ok – Jason Sep 08 '22 at 10:21

1 Answers1

1

I want to know that are the above two highlighted statements UB because x and y are not initialized and the user is passing those to the function by value?

Yes, your understanding is correct. The variable x and y are uninitialized local variables and they're being used/passed by value when calling the functions. Thus, the program has undefined behavior as x and y have indeterminate values and you're using/copying those values to the parameter of the function.

Jason
  • 36,170
  • 5
  • 26
  • 60
  • I wonder why the `value` part is important in this context: despite being passed that way, the actual values are not used in the body of the function, and the compiler still can deduce the types from declarations. E.g. in unevaluated context couldn't, say, `sizeof(x)` be defined behaviour even if `x` is only defined as `int x`? – The Dreams Wind Sep 08 '22 at 05:28
  • 1
    @TheDreamsWind The `value` part is important because there is always a **conceptual copy** when passing argument by value. So even in principle, the program has UB. – Jason Sep 08 '22 at 05:29