Портативная трассировка стека C ++ в исключении

Еще одна возможная причина этого:

Я видел это в журнале:

Не удалось разрешить атрибут

проблема заключалась в том, что я пытался использовать цвет из текущей темы в качестве фона для одного из моих макетов.

, например

android:background="?themeColor"

Изменение этого на определенный цвет устраняло проблему .

android:background="@color/White"
13
задан Community 23 May 2017 в 10:30
поделиться

6 ответов

Я думаю, что это - действительно плохая идея.

Мобильность является очень достойной целью, но не, когда она приводит к решению, которое навязчиво, иссушает производительность, и нижняя реализация.

Каждая платформа (Windows/Linux/PS2/iPhone/etc), я продолжил работать, предложила способ обойти стек, когда исключение происходит, и соответствие адресует к именам функций. Да, ни один из них не портативен, но платформа создания отчетов может быть, и обычно требуется меньше чем день или два для записи определенной для платформы версии кода прохода по стеку.

Не только это меньше времени, чем оно взяло бы создание/поддержание межплатформенного решения, но результаты намного лучше;

  • Никакая потребность изменить функции
  • Прерывания отказывают в библиотеках стандартного или третьего лица
  • Никакая потребность в попытке/выгоде в каждой функции (замедляются и интенсивно использующий память),
21
ответ дан 1 December 2019 в 20:13
поделиться

Искать Nested Diagnostic Context однажды. Вот немного подсказки:

class NDC {
public:
    static NDC* getContextForCurrentThread();
    int addEntry(char const* file, unsigned lineNo);
    void removeEntry(int key);
    void dump(std::ostream& os);
    void clear();
};

class Scope {
public:
    Scope(char const *file, unsigned lineNo) {
       NDC *ctx = NDC::getContextForCurrentThread();
       myKey = ctx->addEntry(file,lineNo);
    }
    ~Scope() {
       if (!std::uncaught_exception()) {
           NDC *ctx = NDC::getContextForCurrentThread();
           ctx->removeEntry(myKey);
       }
    }
private:
    int myKey;
};
#define DECLARE_NDC() Scope s__(__FILE__,__LINE__)

void f() {
    DECLARE_NDC(); // always declare the scope
    // only use try/catch when you want to handle an exception
    // and dump the stack
    try {
       // do stuff in here
    } catch (...) {
       NDC* ctx = NDC::getContextForCurrentThread();
       ctx->dump(std::cerr);
       ctx->clear();
    }
}

Издержки находятся в реализации NDC. Я играл с лениво оцененной версией, а также той, которая только сохранила постоянное число записей также. Ключевой пункт то, что при использовании конструкторов и деструкторов для обработки стека так, чтобы Вам не были нужны все противные try/catch блоки и явное управление везде.

Единственная платформа определенная головная боль getContextForCurrentThread() метод. Можно использовать платформу определенная реализация с помощью локальной памяти потока для обработки задания в большинстве если не все случаи.

Если Вы - больше производительности, ориентированной и живой в мире файлов журнала, то изменяете объем, чтобы содержать указатель на имя файла и номер строки и опустить вещь NDC в целом:

class Scope {
public:
    Scope(char const* f, unsigned l): fileName(f), lineNo(l) {}
    ~Scope() {
        if (std::uncaught_exception()) {
            log_error("%s(%u): stack unwind due to exception\n",
                      fileName, lineNo);
        }
    }
private:
    char const* fileName;
    unsigned lineNo;
};

Это даст Вам хорошее отслеживание стека в Вашем файле журнала, когда исключение будет выдано. Никакая потребность в любом реальном проходе по стеку, просто немного сообщения журнала, когда исключение выдается ;)

6
ответ дан 1 December 2019 в 20:13
поделиться

В отладчике:

Для получения отслеживания стека того, где исключением является бросок от, я просто засовываю точку останова в станд.:: конструктор исключения.

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

1
ответ дан 1 December 2019 в 20:13
поделиться

Я не думаю, что существует "независимый от платформы" способ сделать это - в конце концов, если бы было, то не было бы потребности в StackWalk или специальных функциях трассировки стопки gcc, которые Вы упоминаете.

Это было бы немного грязно, но способ, которым я реализую это, состоял бы в том, чтобы создать класс, который предлагает последовательный интерфейс для доступа к отслеживанию стека, затем имейте #ifdefs в реализации, которые используют соответствующие определенные для платформы методы для фактического соединения отслеживания стека.

Тем путем Ваше использование класса независимо от платформы, и просто что класс должен был бы быть изменен, если бы Вы хотели быть нацеленными на некоторую другую платформу.

2
ответ дан 1 December 2019 в 20:13
поделиться

Это будет медленнее, но похоже на него, должен работать.

Из того, что я понимаю, что проблема в создании быстрого, портативного, отслеживания стека состоит в том, что реализацией стека является и ОС и конкретный ЦП, таким образом, это - неявно платформа определенная проблема. Альтернатива должна была бы использовать функции MS/glibc и использовать #ifdef, и соответствующий препроцессор определяет (например, _WIN32) для реализации платформы определенные решения в различных сборках.

0
ответ дан 1 December 2019 в 20:13
поделиться

Так как использование стека является высоко платформой и зависящий от реализации, нет никакого способа сделать это непосредственно, который является абсолютно портативным. Однако Вы могли создать портативный интерфейс на платформу и компилятор определенная реализация, локализовав проблемы как можно больше. По моему скромному мнению, это было бы Вашим лучшим подходом.

Реализация трассировщика затем связалась бы с любой платформой, определенные библиотеки помощника доступны. Это затем работало бы только, когда исключение происходит, и даже затем, только если Вы назвали его от блока выгоды. Его минимальный API просто возвратил бы строку, содержащую целую трассировку.

Требование, чтобы кодер ввел выгоду и обработку переброска в цепочке вызовов, имеет значительные затраты во время выполнения на некоторых платформах и налагает большую будущую стоимость обслуживания.

Тем не менее, если Вы действительно принимаете решение использовать механизм выгоды/броска, не забывайте, что даже C++ все еще имеет препроцессор C в наличии, и что макросы __FILE__ и __LINE__ определяются. Можно использовать их для включения имени исходного файла и номера строки в трассировочной информации.

0
ответ дан 1 December 2019 в 20:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: