STL Filter — скрипт для лаконичных ошибок STL

C++*
STL славится своей способностью заполнять метры экранного пространства сообщениями об ошибках. Надоело смотреть на экран и видеть перлы вроде:

testmap.cpp:25: error: no matching function for call to ‘std::map<int, double, std::less, std::allocator<std::pair<const int, double> > >::map(int, int, int)’
/usr/include/c++/4.3/bits/stl_map.h:175: note: candidates are: std::map<_Key, _Tp, _Compare, _Alloc>::map(const std::map<_Key, _Tp, _Compare, _Alloc>&) [with _Key = int, _Tp = double, _Compare = std::less, _Alloc = std::allocator<std::pair<const int, double> >]
/usr/include/c++/4.3/bits/stl_map.h:165: note: std::map<_Key, _Tp, _Compare, _Alloc>::map(const _Compare&, const _Alloc&) [with _Key = int, _Tp = double, _Compare = std::less, _Alloc = std::allocator<std::pair<const int, double> >]


ну и еще пара десятков строк.



Решение проблемы длиннющих ошибок заключается в том чтобы использовать фильтры вывода STL. Об одном таком фильтре, stlfilt, рассказал Скотт Мейерс в своей книге Effective STL.

Пример использования


Имеем код с ошибками в использовании std::map:
#include <iostream>
#include <map>
#include <algorithm>
#include <cmath>
using namespace std;

const int values[] = { 1,2,3,4,5 };
const int NVALS = sizeof values / sizeof (int);

struct intComp: public binary_function<int, int, bool>
{
  bool operator()(int a, int b) const
  {
    return a < b;
  }
};

int main()
{
  using namespace std;

  typedef map<int, double> valmap;
  typedef map<int *, double *> pmap;
  
  valmap m2(1,2,3);
  pmap m3(1,2,3);
  map<int, double, intComp> valmap3;

  valmap m;
  pmap p;
  
  for (int i = 0; i < NVALS; i++)
  {
    m.insert(make_pair(values[i], pow(values[i], .5)));
    valmap3.insert(0);
  }

  valmap::iterator it = 100;
  valmap::const_iterator cit = 100;
  
  m.insert(1,2);
  m.insert(make_pair(36, 10.57)); // fine, more convenient
  m.insert(m.end(), make_pair(40, 2.29)); // also fine
  return 0;
}

* This source code was highlighted with Source Code Highlighter.


вместо g++ testmap.cpp выполняем gfilt testmap.cpp. Результат:
testmap.cpp: In function ‘int main()’:
testmap.cpp:25: error: No match for ‘map<int, double>::map(int, int, int)’
testmap.cpp:26: error: No match for ‘map<int *, double *>::map(int, int,
int)’
testmap.cpp:35: error: No match for ‘map<int, double, intComp>::insert(
int)’
testmap.cpp:38: error: conversion from ‘int’ to non-scalar type ‘gen_map<
int, double>::iterator’ requested
testmap.cpp:39: error: conversion from ‘int’ to non-scalar type ‘gen_map<
int, double>::const_iterator’ requested
stl_tree.h: In member function ‘void map<
int, double>::_M_insert_unique(_II, _II)’:
[STL Decryptor: Suppressed 1 more STL standard header message]
testmap.cpp:41: instantiated from here
stl_tree.h:1295: error: invalid type argument of ‘unary *’

На мой взгляд, это выглядит куда симпатичнее.

Установка


Установка и настройка проста:
  • скачать STLFilt
  • распаковать архив
  • в скрипте-оболочке gfilt написать COMPILER=g++. Мне еще не нравится использование less при выводе, убрать его из переменной PAGER.
  • Все, теперь оболочка передает все ключи g++, принимает от него информацию об ошибках. парсит её и выдает нам.
+24
8 ноября 2009, 20:58
23
ganqqwerty 26,7

комментарии (35)

+2
sometime_sniff #
Весьма полезная информация. Спасибо.
А как эта штука реагирует на остальные ошибки, не связанные с шаблонами? Вы проводили более масштабное тестирование, если можно так выразиться?
+1
ganqqwerty #
Увы, на остальные ошибки она забивает. Каких вам еще ошибок не хватает? Вот мне бы очень бы понравилась иная обработка ошибки «отсутствие точки с запятой в конце определения класса».
А этот скриптик просто сворачивает на место typedef'ы и убирает лишние параметры шаблонов.
+2
jeck_landin #
Можно ли его использовать для фильтрации вывода компилятора таким образом: "g++ testmap.cpp | gfilt"?
+3
ganqqwerty #
не-а. Это первое, что я решил попробовать до чтения мана. (:
0
akalend #
думаю, если этот фильтр чуть пропатчить, то можно. На мой взгяд — не сложно.
+1
sometime_sniff #
Я спрашивал подовляет она или не изменяет другие ошибки? например про точки с запятой. Если нет то, хорошо. А вообще, сдается мне, что «лишних параметров шаблонов» не бывает ;)
+3
ganqqwerty #
К тому времени, когда аллокаторы станут для меня не лишними, а вполне понятными и легкими параметрами, я буду читать STL-ные сообщения даже в двоичном виде и нараспев.
+1
tavi #
Давно ждал что-то подобное, а написать руки не дошли. Спасибо.
+1
fata1ex #
Мелочь, но приятно :) Спасибо
0
Xronos #
По мойму, костыль этот проблему не решает, а добавляет еще кучу, надо сначала через gfilt запускать компилирование, а потом если не получилось, запускать gcc заново, смотреть другой отчет об ошибках? А ошибки в шаблонах так и не научились ловить во время компиляции?
+3
ganqqwerty #
Вы, похоже, не выспались.
> потом если не получилось, запускать gcc заново
что не получилось или может не получиться? gcc и так запускается, парсится только вывод об ошибках.
> А ошибки в шаблонах так и не научились ловить во время компиляции?
Тут речь идет только о компиляции. Ошибки все отлично ловятся и без этого скрипта, но stlfilt повышает информативность выводаю
+2
Xronos #
> Вы, похоже, не выспались.
ну да, точней еще не ложился. )
По работе переключился на C#, сейчас недавние траблы с с++ вспоминать не хочется. Статья хорошая, кому-то надеюсь пригодится. А в vs похожий фильтр встроить можно чтобы Output фильтровал?
+3
sometime_sniff #
Да, там на страничке есть скриты для всех версий MSVS 200X (:
0
superhabra #
Настоящий C++ программист должен уметь читать такие ощибки :)
0
torkve #
Я постеснялся это написать))
0
akalend #
жаль, что не могу поставить + за ответ…
за-то смог обеть карму.
0
akalend #
где-то у того же Скота Майерса было написано, как читать такие ошибки.
Вообще-то настоящий программист должен уметь не допускать такие ошибки.
+1
torkve #
Плохо, что с ним не будет работать, например, ccache.
+1
jcmvbkbc #
а собственно, почему нет, если ccache/distcc использовать через символьные ссылки?
+1
torkve #
Потому что ccache и так работает через символьные ссылки gcc->ccache, g++->ccache etc. Он детектит тип компилятора через имя запускаемого файла. Если оно будет gfilt, ccache тупо не поймёт, какой компилятор использовать.
+1
jcmvbkbc #
Я это и имел в виду: gfilt вызывает g++, который симлинк на ccache.
В итоге CXX=gfilt и всё работает.
+1
torkve #
Я подозреваю, что в этом случае ccache увидит имя бинарника как «gfilt», а не как «g++», в этом проблема. Впрочем, надо протестить.
+3
Volfram #
Сообщения STL об ошибках кажутся длинными только тому, кто не работал с boost: ) Но вещица удобная. Впрочем, если постоянно работать с шаблонами в С++, вскоре начинаешь догадываться о том, какая может быть ошибка просто по наличию сообщения, толком его не читая.
+2
sometime_sniff #
Еще одна идея для тестирования этой штуковины. Подсуньте ей на вход какой-нибудь шаблон из boost. А можно сразу смесь чего-нибудь из boost. Интересно как она отреагирует на такие «ругательства».
0
ganqqwerty #
там кажися внутри правила типа: замени std::map<куча параметров> на std::map<2-3 параметра>. Для буста, получается, нужен отдельный скриптик
+1
sometime_sniff #
А точно. он же только STL фильтр. не обратил внимание.
+1
nuit #
в gcc-trunk(4.5) не печатаются дефолтные аргументы параметров.
>test.cpp:25:18: error: no matching function for call to ‘std::map<int, double>::map(int, int, int)’
+1
ganqqwerty #
красотища! Значит, проект скоро (через годика 3, когда все перейдут на новый gcc) станет никому не нужным. (:
+1
nuit #
Да и сейчас не так уж много проблем вызывают подобные строчки, вполне читабельно.

Free Image Hosting at www.ImageShack.us
+1
torkve #
Цветовой схемой и списком не поделитесь?)
Особенно интересно, как Вы список ошибок в отдельное окно выносите и подсвечиваете.
+1
torkve #
списком плагинов*
+1
nuit #
>Цветовой схемой и списком не поделитесь?)
(defun color-theme-qb ()
"Color theme"
(interactive)
(color-theme-install
'(color-theme-qb
((background-color . "#141414")
(background-mode . dark)
(border-color . "black")
(cursor-color . "#A7A7A7")
(foreground-color . "#F8F8F8")
(mouse-color . "sienna1"))
(default ((t (:background "#141414" :foreground "#CACACA"))))
(modeline ((t (:background "#999999" :foreground "black" :box
(:line-width 1 :style
released-button)))))
(border-glyph ((t (nil))))
(buffers-tab ((t (:background "#141414" :foreground "#CACACA"))))
(font-lock-builtin-face ((t (:foreground "#CACACA"))))
(font-lock-comment-face ((t (:foreground "#5F5A60"))))
(font-lock-constant-face ((t (:foreground "#CF6A4C"))))
(font-lock-doc-string-face ((t (:foreground "DarkOrange"))))
(font-lock-function-name-face ((t (:foreground "#9B703F"))))
(font-lock-keyword-face ((t (:foreground "#CDA869"))))
(font-lock-preprocessor-face ((t (:foreground "Aquamarine"))))
(font-lock-reference-face ((t (:foreground "SlateBlue"))))
(font-lock-string-face ((t (:foreground "#8F9D6A"))))
(font-lock-type-face ((t (:foreground "#9B703F"))))
(font-lock-variable-name-face ((t (:foreground "#7587A6"))))
(font-lock-warning-face ((t (:background "#660000" :foreground "red"))))
(font-lock-regexp-grouping-backslash ((t (:foreground "#E9C062"))))
(font-lock-regexp-grouping-construct ((t (:foreground "red"))))

(minibuffer-prompt ((t (:foreground "#5F5A60"))))
(ido-subdir ((t (:foreground "#CF6A4C"))))
(ido-first-match ((t (:foreground "#8F9D6A"))))
(ido-only-match ((t (:foreground "#8F9D6A"))))
(mumamo-background-chunk-submode ((t (:background "#222222"))))

(gui-element ((t (:background "#D4D0C8" :foreground "black"))))
(region ((t (:background "#27292A"))))
(mode-line ((t (:background "grey75" :foreground "black"))))
(highlight ((t (:background "#111111"))))
(highline-face ((t (:background "SeaGreen"))))
(text-cursor ((t (:background "yellow" :foreground "black"))))
(zmacs-region ((t (:background "snow" :foreground "blue"))))

(show-paren-match-face
((t (:foreground "#2e3436" :background "#73d216"))))
(show-paren-mismatch-face
((t (:background "#ad7fa8" :foreground "#2e3436"))))
(isearch ((t (:background "#222222"))))
(isearch-lazy-highlight-face
((t (:foreground "#2e3436" :background "#e9b96e"))))
(flymake-errline ((t (:background "DarkRed"))))
(flymake-warnline ((t (:background "DarkYellow"))))
(primary-selection ((t (:background "#444444"))))
(secondary-selection ((t (:background "#666666")))))))

>как Вы список ошибок в отдельное окно выносите и подсвечиваете.
emacs > compile
+1
torkve #
Горе мне, я думал, это vim)
Извините)
0
ganqqwerty #
И я тоже!!! (Посыпает голову пеплом) Ну да ладно, надо все равно погуглить на тему vim error hightlighting.
+1
elw00d #
В принципе, ошибки такого плана возникают не так уж часто. Причем в более чем половине случаев с первого взгляда на строчку уже понятно, в чем проблема. А если не ясно — то можно и прочитать детали.
С другой стороны, может, кому-нибудь и пригодится.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.