{ }codelper

Learn › C++

Going further · 22

Common mistakes and error messages

How to read error messages, and the mistakes every language shares: off-by-one, = vs ==, integer division, null, out-of-range indexes.

Some mistakes show up in every language.
Learn them together with how to read error messages.
The example below checks that an index is in range and that the divisor isn't 0 before using them.

#include <cstdio>#include <iostream>#include <optional>#include <vector> // optional<int>는 '수 또는 없음'이에요std::optional<int> get(const std::vector<int>& a, int i) {    if (i < 0 || i >= (int)a.size()) return std::nullopt; // a[i]는 검사 안 함, a.at(i)는 예외    return a[i];} std::optional<int> safeDiv(int x, int y) {    if (y == 0) return std::nullopt; // 0으로 나누면 정의되지 않은 동작    return x / y;} int main() {    int n, q, x, y;    std::cin >> n;    std::vector<int> a(n);    long long sum = 0; // = 0 을 빼면 쓰레기 값에서 시작해요    for (int& v : a) std::cin >> v, sum += v;    std::cin >> q;    for (int t = 0; t < q; t++) {        int i;        std::cin >> i;        if (auto v = get(a, i)) std::cout << "a[" << i << "] = " << *v << '\n';        else std::cout << "a[" << i << "]: out of range\n";    }    std::cin >> x >> y;    if (auto d = safeDiv(x, y)) std::cout << x << " / " << y << " = " << *d << '\n';    else std::cout << x << " / " << y << ": cannot divide\n";    std::printf("average %.1f\n", (double)sum / n); // sum / n은 2}
stdin
5
3 1 4 1 5
3
2 7 -1
7 0
stdout
a[2] = 4
a[7]: out of range
a[-1]: out of range
7 / 0: cannot divide
average 2.8

Key points

  • In an error message, look for the error name, the reason and the line number.
    In Python, read from the bottom line.
  • In compiled languages (C, C++, Java, C#), fix the first error first, even when there are many.
    The later ones are often knock-on effects.
  • Indexes run from 0 to n - 1, so a loop needs i < n.
    Writing i <= n steps one past the end: the off-by-one error.
  • = stores, == compares.
  • Before dividing, check the divisor isn't 0.
    Before using a value, check it isn't null.
  • Give every variable a starting value when you create it (int sum = 0;).

How each language writes it

PythonThe last line has the name and reason, like IndexError: list index out of range, with the line number just above.
Dividing by 0 raises ZeroDivisionError, calculating with None raises TypeError, an unknown name raises NameError.
a[-1] isn't an error but the last item, and if not v: also catches 0 (ask v is None)
JavaScriptAn out-of-range index gives undefined with no error, and 7 / 0 is Infinity.
"No value" is null and undefined, and undefined + 1 is NaN while null + 1 is 1, so it goes quietly wrong.
Compare with === ("1" == 1 is true)
TypeScriptSame as JavaScript
JavaThe first line is ArrayIndexOutOfBoundsException: Index 7 out of bounds for length 5, and at Main.main(Main.java:12) below gives the line.
Dividing by 0 throws ArithmeticException, null throws NullPointerException (int can't hold it, so use Integer).
A variable with no starting value is a compile error: "might not have been initialized"
C#Out of range throws IndexOutOfRangeException, dividing by 0 throws DivideByZeroException.
"No value" is int?.
A variable with no starting value is compile error CS0165
C++a[i] doesn't check, so out of range is undefined behaviour; a.at(i) throws std::out_of_range.
Integer division by 0 is undefined behaviour too (usually a crash).
"No value" is std::optional.
int sum; starts with a garbage value
CArrays aren't checked, so out of range is undefined behaviour: a garbage value, another variable overwritten, or a crash.
Division by 0 and uninitialized locals behave as in C++
CraykonOut of range stops with "List only has indexes 0–4".
7 / 0 is Infinity; Mathf.Quot(7, 0) stops with "Can't divide by 0".
null + 1 stops with "Can't calculate with null" (joined to text it shows as 빈값), and an unknown name "hasn't been created yet"

Common mistakes

i <= n stepped past the endC · C++ · Java · C# · JavaScript · TypeScript

int sum = 0;
for (int i = 0; i <= n; i++)
    sum += a[i];

→ Java and C# throw an out-of-range exception, JavaScript adds undefined and gets NaN, and C quietly adds a garbage value

Write i < n.

= instead of ==C · C++ · JavaScript

if (x = 5) {
    puts("five");
}

→ No error: 5 is stored in x and the condition is always true (gcc -Wall warns about it)

Compare with ==.
Java and C# refuse to compile, Python raises SyntaxError (since 3.10: "Maybe you meant '=='"), and Craykon rejects it as a syntax error.

The average came out wholeJava · C# · C · C++

int sum = 7, n = 2;
double avg = sum / n;

→ avg is 3.0: 7 / 2 is integer division, so the fraction is dropped first

Convert one side first: (double)sum / n.

How languages differ
An error that stops your program is actually a favour.
The truly scary cases give a wrong value with no error, like out-of-range access in C/C++ or undefined in JavaScript.

Practice