Почему printf () останавливает сбой? - PullRequest
2 голосов
/ 21 мая 2011

Я искал во всем Интернете ответ на этот вопрос (см. Тему сообщения). Мне задавали этот точный вопрос дважды. Однажды на собеседовании в компании, а однажды у друга, и я не могу найти ответ на мою жизнь.

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

Спасибо, Мэтью Хогган

Я сейчас читаю предоставленную ссылку, но для дальнейшего разговора я опубликовал некоторые из моих слабых попыток расследования:

Хорошо, так что я начал играть вокруг себя, чтобы попытаться ответить на свой вопрос, но мне все еще не до конца понятно. Ниже приведен вывод компилятора g ++ с использованием опции -S для вывода сборки вместо исполняемого файла. Эквивалентный код C ++ также размещен ниже. Моя цель - попытаться воссоздать простой сценарий, а затем попытаться определить, основываясь на инструкциях, что может происходить на уровне процессора. Итак, скажем, сразу после кода ассемблера "call printf", который, как я предполагаю, связан с библиотечными файлами, хранящимися в / usr / lib или другом каталоге lib, я попытался получить доступ к NULL-указателю (не в коде) или к другому форма работы, которая традиционно вылетает из программы. Я предполагаю, что мне нужно было бы выяснить, что printf делает инструкцию, чтобы глубже взглянуть на это?

.file   "assembly_test_printf.cpp"

        .section    .rodata

.LC0:

    .string "Hello World"

    .text

.globl main

    .type   main, @function

main:

.LFB0:

    .cfi_startproc

    .cfi_personality 0x0,__gxx_personality_v0

    pushl   %ebp

    .cfi_def_cfa_offset 8

    movl    %esp, %ebp

    .cfi_offset 5, -8

    .cfi_def_cfa_register 5

    andl    $-16, %esp

    subl    $32, %esp

    movl    $0, 28(%esp)

    movl    $.LC0, (%esp)

    call    printf

    movl    28(%esp), %eax

    leave

    ret

    .cfi_endproc

.LFE0:

    .size   main, .-main

    .ident  "GCC: (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5"

    .section    .note.GNU-stack,"",@progbits

Эквивалентный код C ++:

#include <stdio.h>

int main ( int argc, char** argv ) {

    int x = 0;

    printf ("Hello World"); 

    return x;
}

Ответы [ 2 ]

8 голосов
/ 21 мая 2011

Существует несколько причин, по которым добавление printf() может изменить поведение ошибки.Некоторые из наиболее распространенных могут быть:

  • изменение времени выполнения (особенно для потоковых ошибок)
  • изменение шаблонов использования памяти (компилятор может изменить способ использования стека)
  • изменение способа использования регистров

Например, неинициализированная локальная переменная может быть назначена регистру.Перед добавлением printf() используется неинициализированная переменная, которая получает значение мусора, которое находится в регистре (возможно, результат предыдущего вызова rand(), поэтому он действительно не определен).Добавление printf() приводит к тому, что регистр будет использоваться в printf(), а printf() всегда оставляет этот регистр установленным на 0 (или что-то еще).Теперь ваша глючная программа все еще глючит, но с другим поведением.И, возможно, такое поведение оказывается добрым.

1 голос
/ 21 мая 2011

Я видел это раньше, например, в Java, в тех случаях, когда код инициализации не завершен, когда другой поток пытается получить доступ к объекту, предположительно уже созданному. System.out.println () замедляет другой поток достаточно для завершения инициализации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...