4

The following code throws an exception when it is run under Visual Studio 2013 but not gcc 4.9.2.

The error reported is:

'exception: stol argument out of range'

stol returns a long so the size of temp should be big enough to hold the returned value.

Can anyone explain the behaviour. Is this possibly a compiler bug?

#include <iostream>
#include <exception>
#include <string>
#include <stdexcept>

int main()
{
    const std::string value = "4294967295";   // 0xffffffff

    try
    {
        int64_t temp = std::stol(value);
    }

    catch (std::invalid_argument& ex)
    {
        std::cout << "invalid_argument: " << ex.what() << "\n";
    }

    catch (std::exception& ex)
    {
        std::cout << "exception: " << ex.what() << "\n";
    }

   return 0;
}
Praetorian
  • 106,671
  • 19
  • 240
  • 328
ksl
  • 4,519
  • 11
  • 65
  • 106

5 Answers5

5

My bet would be a 32 bits long on visual studio (max 2^31, so overflow) and a 64 bits long on GCC (so nowhere near overflow).

MSalters
  • 173,980
  • 10
  • 155
  • 350
5

Under Windows the type long is always 32-bits. Since long is a signed integer type this means that the range of long is between -2147483648 and 2147483647 inclusive. On Linux the size of long depends on whether you're compiling for 32-bits or 64-bits.

Since std:stol converts a string to long the result must fit into a long. If it doesn't then the function throws std::out_of_range. To resolve this problem you can use std::stoll which returns a long long, which is guaranteed to be at least 64-bits and so won't ever throw an exception when converting "4294967295". You can also use std::stoul, which converts to a unsigned long, which is is guaranteed to have a range of at least 0 to 4294967295.

(Note that this is not strictly a Visual C++ versus GCC thing. When targeting Windows, GCC also always uses a 32-bit long.)

Ross Ridge
  • 38,414
  • 7
  • 81
  • 112
3

Not a compiler bug, the problem is your invalid assumptions.

The Standard allows LONG_MAX to be as low as 2147483647, so

stol returns a long so the size of temp should be big enough to hold the value.

simply is not true.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
1

So just use std::stoul instead.

At first glance the string constant certainly exceeds the maximum value a long can assume, but not the max value an unsigned long can have...

TobiMcNamobi
  • 4,687
  • 3
  • 33
  • 52
0

From

http://en.cppreference.com/w/cpp/string/byte/strtol

strtol returns a long and you need strtoll to get a long long

marom
  • 5,064
  • 10
  • 14