Подтвердить что ты не робот

Какова функция этого утверждения * (long *) 0 = 0;?

В следующем коде *(long*)0=0; используется вместе с предложением if, но в чем его цель?

if(r.wid*r.ht < tot)
    *(long*)0=0;
4b9b3361

Ответ 1

Он записывает 0 в 0, интерпретируемый как адрес long, то есть указатель NULL. Это неправдоподобно, поскольку NULL никогда не является адресом, на котором вы можете иметь достоверные данные, доступ к которым может получить ваша программа. Этот код вызывает поведение undefined; вы не можете полагаться на него, чтобы иметь какой-то конкретный эффект в целом.

Однако часто такой код используется для принудительной сбой segmentation fault, что иногда удобно отбрасывать в отладчик.

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

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

Ответ 2

В учебнике C abort есть способ умышленного сбоя программы. Однако, когда вы программируете рядом с металлом, вам, возможно, придется беспокоиться о возможности abort не работать так, как предполагалось! Стандартная реализация POSIXy abort вызывает getpid и kill (через raise), чтобы доставить SIGABRT к процессу, что, в свою очередь, может привести к выполнению обработчика сигнала, который может делать по своему усмотрению. Возможны ситуации, например. глубоко в кишках malloc, в ответ на катастрофическое, возможно, сокрушительное повреждение памяти, когда вам нужно принудительно вызвать сбой, не касаясь стека вообще (в частности, без выполнения команды возврата, которая может перейти на вредоносный код). *(long *)0 = 0 не самая сумасшедшая вещь, чтобы попытаться в этих обстоятельствах. Он все еще рискует выполнить обработчик сигналов, но это неизбежно; нет способа вызвать SIGKILL без вызова функции. Более серьезно (IMHO) современные компиляторы, скорее всего, это заметят, заметили, что он имеет поведение undefined, удаляет его и также удаляет тест, потому что тест не может быть когда-либо прав, потому что никто не будет намеренно вызывают поведение undefined, не так ли? Если такая логика кажется порочной, прочитайте раздел LLVM в разделе undefined поведение и оптимизация (часть 2, часть 3).

Есть лучшие способы достижения этой цели. Многие компиляторы в настоящее время имеют встроенный (например, gcc, clang: __builtin_trap()), который генерирует машинную команду, которая гарантированно приведет к сбою оборудования и доставке SIGILL; в отличие от трюков undefined с указателями, компилятор не будет оптимизировать это. Если ваш компилятор не имеет этого, но имеет сборные вставки, вы можете вручную вставить такую ​​инструкцию - это, вероятно, достаточно низкий уровень кода, что дополнительный бит машинной зависимости не имеет большого значения. Или вы можете просто позвонить _exit. Это, пожалуй, самый безопасный способ воспроизвести его, потому что он не рискует работать с обработчиками сигналов, и он не возвращает никаких функций даже внутри. Но это означает, что вы не получаете дамп ядра.

Ответ 3

Чтобы программа "выходила ненормально", используйте функцию abort() (http://pubs.opengroup.org/onlinepubs/9699919799/functions/abort.html).

Стандартная идиома C/С++ для "если условие X неверно, сделать программу анонимно" - это макрос assert(). Код выше был бы лучше написан:

assert( !(r.wid*r.ht < tot) );

или (если вы с удовольствием игнорируете случаи краев), он читается более чисто:

assert( r.wid*r.ht >= tot );

Ответ 4

Если ширина разницы в высоте r меньше, чем общая, выполните сбой программы.