Как я могу утверждать (), не используя аварийное прекращение работы ()?

Если вы не хотите использовать jQuery в решении, вы можете попробовать это. Решение, взятое здесь https://stackoverflow.com/a/1714899/1784301

$http({
    method: 'POST',
    url: url,
    headers: {'Content-Type': 'application/x-www-form-urlencoded'},
    transformRequest: function(obj) {
        var str = [];
        for(var p in obj)
        str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
        return str.join("&");
    },
    data: xsrf
}).success(function () {});

24
задан Patrick Desjardins 3 October 2008 в 20:04
поделиться

5 ответов

1118 Да, на самом деле, есть. Вам нужно будет написать собственную функцию assert самостоятельно, так как assert() в C ++ - это точно C assert(), с включенной «функцией» abort(). К счастью, это удивительно просто.

Assert.hh

template <typename X, typename A>
inline void Assert(A assertion)
{
    if( !assertion ) throw X();
}

Вышеприведенная функция вызовет исключение, если предикат не выполняется. Тогда у вас будет шанс поймать исключение. Если вы не поймаете исключение, будет вызвано terminate(), что завершит программу аналогично abort().

Вы можете спросить, как насчет оптимизации утверждения, когда мы создаем для производства. В этом случае вы можете определить константы, которые будут означать, что вы создаете для производства, а затем сослаться на константу, когда вы Assert().

debug.hh

#ifdef NDEBUG
    const bool CHECK_WRONG = false;
#else
    const bool CHECK_WRONG = true;
#endif

main.cc

#include<iostream>

struct Wrong { };

int main()
{
    try {
        Assert<Wrong>(!CHECK_WRONG || 2 + 2 == 5);
        std::cout << "I can go to sleep now.\n";
    }
    catch( Wrong e ) {
        std::cerr << "Someone is wrong on the internet!\n";
    }

    return 0;
}

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

Функция Assert() эквивалентна вводу

if( !assertion ) throw X();

, но она ясно указывает на намерение программиста: сделать утверждение. Утверждения также легче найти при таком подходе, как простые assert() с.

Подробнее об этом методе см. Бьярн Страуструп «Язык программирования C ++ 3e», раздел 24.3.7.2.

25
ответ дан wilhelmtell 28 November 2019 в 23:25
поделиться

Функции сообщения об ошибках glib используют подход продолжения после подтверждения. glib - это базовая библиотека независимости платформ, которую использует Gnome (через GTK). Вот макрос, который проверяет предусловие и печатает трассировку стека в случае сбоя предусловия.

#define RETURN_IF_FAIL(expr)      do {                  \
 if (!(expr))                                           \
 {                                                      \
         fprintf(stderr,                                \
                "file %s: line %d (%s): precondition `%s' failed.", \
                __FILE__,                                           \
                __LINE__,                                           \
                __PRETTY_FUNCTION__,                                \
                #expr);                                             \
         print_stack_trace(2);                                      \
         return;                                                    \
 };               } while(0)
#define RETURN_VAL_IF_FAIL(expr, val)  do {                         \
 if (!(expr))                                                       \
 {                                                                  \
        fprintf(stderr,                                             \
                "file %s: line %d (%s): precondition `%s' failed.",     \
                __FILE__,                                               \
                __LINE__,                                               \
                __PRETTY_FUNCTION__,                                    \
                #expr);                                                 \
         print_stack_trace(2);                                          \
         return val;                                                    \
 };               } while(0)

Вот функция, которая печатает трассировку стека, написанная для среды, которая использует цепочку инструментов gnu (gcc):

void print_stack_trace(int fd)
{
    void *array[256];
    size_t size;

    size = backtrace (array, 256);
    backtrace_symbols_fd(array, size, fd);
}

Вот как вы можете использовать макросы:

char *doSomething(char *ptr)
{
    RETURN_VAL_IF_FAIL(ptr != NULL, NULL);  // same as assert(ptr != NULL), but returns NULL if it fails.

    if( ptr != NULL )        // Necessary if you want to define the macro only for debug builds
    {
       ...
    }

    return ptr;
}

void doSomethingElse(char *ptr)
{
    RETURN_IF_FAIL(ptr != NULL);
}
11
ответ дан indiv 28 November 2019 в 23:25
поделиться

Утверждения в C / C ++ выполняются только в отладочных сборках. Так что это не произойдет во время выполнения. В общем, утверждения должны отмечать вещи, которые, если они случаются, указывают на ошибку, и, как правило, отображать предположения в вашем коде и т. Д.

Если вы хотите иметь код, который проверяет ошибки во время выполнения (в выпуске), вы, вероятно, должны использовать исключения а не утверждает, что это то, для чего они предназначены. Ваш ответ в основном заключает исключение в синтаксис assert. Хотя это сработает, я не вижу в этом особого преимущества, если прежде всего выбрасывать исключение.

6
ответ дан Ben Childs 28 November 2019 в 23:25
поделиться

Вот что у меня есть в «assert.h» (Mac OS 10.4):

#define assert(e) ((void) ((e) ? 0 : __assert (#e, __FILE__, __LINE__)))
#define __assert(e, file, line) ((void)printf ("%s:%u: failed assertion `%s'\n", file, line, e), abort(), 0)

Исходя из этого, замените вызов abort () на throw (исключение). И вместо printf вы можете отформатировать строку в сообщение об ошибке исключения. В конце вы получите что-то вроде этого:

#define assert(e) ((void) ((e) ? 0 : my_assert (#e, __FILE__, __LINE__)))
#define my_assert( e, file, line ) ( throw std::runtime_error(\
   std::string(file:)+boost::lexical_cast<std::string>(line)+": failed assertion "+e))

Я не пытался скомпилировать это, но вы понимаете смысл.

Примечание: вам нужно убедиться, что заголовок «исключение» всегда включен, а также буст (если вы решите использовать его для форматирования сообщения об ошибке). Но вы также можете сделать my_assert функцией и объявить только ее прототип. Что-то вроде:

void my_assert( const char* e, const char* file, int line);

И реализовать его где-нибудь, где вы можете свободно включать все заголовки, которые вам нужны.

Оберните его в #ifdef DEBUG, если вам это нужно, или нет, если вы всегда хотите запускать эти проверки.

5
ответ дан rlerallut 28 November 2019 в 23:25
поделиться

Если вы хотите добавить символьную строку с информацией об утверждении: http://xll8.codeplex.com/SourceControl/latest#xll/ensure.h

0
ответ дан Keith A. Lewis 28 November 2019 в 23:25
поделиться
Другие вопросы по тегам:

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