zakharvoit's blog

By zakharvoit, 3 years ago, In Russian,

Мало кто знает, но компиляторы и стандартная библиотека C++ могут проверять выходы за границы массивов и векторов.

Если мы используем gcc и glibc, то следующий код бросит исключение:

#define _GLIBCXX_DEBUG

#include <bits/stdc++.h>

int main() {
    std::vector <int> a(100);
    int x = -1;
    printf("%d\n", a[x]);
}

И мы получим примерно вот такой вывод: error: attempt to subscript container with out-of-bounds index -1, but container only holds 100 elements.

Номер строки мы не узнаем, но лучше, чем ничего. С этим флагом все контейнеры С++ включают проверки на ошибки (кроме C++11 std::array, как я понял). Также можно не писать define прямо в коде, а передавать аргумент компилятору: g++ -D_GLIBCXX_DEBUG main.cpp -o main

А что делать с массивами? Для проверки выхода за границы массива предусмотрен флаг -fsanitize=bounds. Правда у меня его gcc(4.7.3) не принял, сказав, что неизвестный флаг, но clang скомпилировал.

#include <bits/stdc++.h>

int main() {
    int a[100];
    int x = -1;
    printf("%d\n", a[x]);
}

Компилируем вот так: clang++ main.cpp -fsanitize=bounds -o main

При запуске получаем: test.cpp:6:20: runtime error: index -1 out of bounds for type 'int [100]

Еще более дружелюбный вывод, чем в случае с векторами.

К сожалению c динамическими массивами (int *a = new int[100]) такое не работает, но есть еще флаг -fsanitize=undefined (включает в себя bounds) и -fsanitize=adress, который как раз уронит вариант с динамическим массивом.

UPD: WARNING: Не отсылайте решения с этим макросом в коде, неизбежно получите ТЛ.

UPD2: Чтобы использовать -fsanitize нужен gcc >=4.9 или clang

 
 
 
 
  • Vote: I like it  
  • +77
  • Vote: I do not like it  

»
2 years ago, # |
  Vote: I like it 0 Vote: I do not like it

Would you translate this to English please?

  • »
    »
    2 years ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    Briefly, the post says that the _GLIBCXX_DEBUG define causes throwing exceptions when trying to access an STL container at an out-of-bounds index, and the -fsanitize=address,undefined command line key for compilers does a simular trick with the arrays. Of course, it affects performance pretty much, so it’s a bad idea to submit the code containing #define _GLIBCXX_DEBUG.