Error in c++: "terminate called after throwing an instance of 'std::length_error' what(): basic_string::_M_replace_aux"

I have a simple function that takes a string of digits and turns them into a floating-point number, the function is underneath:

float convertStrToFloatNumber (std::string n) {
    // Converts the number n to a float in the form of 000.000
    if (6 - n.length() > 0) {
        // The representation is with trailing zeros
        n.append(6 - n.length(), '0');
    }
    // Insert . at the 3. spot
    n.insert(3, ".");
    return strtof((n).c_str(), 0);
}

How ever i throws the following exception when run with the input "030000":

"terminate called after throwing an instance of 'std::length_error' what(): basic_string_M_repalce_aux" what im really interested in is understanding what the last part of the error means.

Upvotes: 0

Views: 4397

Answers (2)

molbdnilo
molbdnilo

Reputation: 66441

Since n.length() is unsigned, 6 is promoted to the same unsigned type, and when the length is greater than six the subtraction will wrap around and produce a huge positive number.

The most robust (and shortest) solution is to avoid the subtraction completely;

if (n.length() < 6)
{
    n.resize(6, '0');
}

Upvotes: 0

Yksisarvinen
Yksisarvinen

Reputation: 22334

The issue does not occur for "030000", but for any string longer than 6 characters.

std::string::length() returns unsigned type. Due to integral promotion rules, 6 gets promoted to unsigned type and you perform subtraction on unsigned types. Underflow on unsigned types result in wraparound, so 0 - 1u is equal to std::numeric_limits<unsigned>::max() (if unsigned is 32-bit, then it's equal to 2^32 - 1 = 4294967295)


You can simply change the logic of condition:

if (n.length() < 6)

Or cast the length to signed type:

if (6 - static_cast<int>(n.length()) > 0)

Upvotes: 3

Related Questions