Странное поведение при использовании getchar() и -O3

У меня есть эти две функции

    void set_dram_channel_width(int channel_width){
      printf("one\n");
          getchar();
    }


    void set_dram_transaction_granularity(int cacheline_size){
      printf("two\n");
          getchar();
    }
    //output:
    one
    f //my keyboard input
    two
    one
    f  //keyboard input
    two
    one
    f  //keyboard input
    //No more calls

Затем я меняю функции на:

    void set_dram_channel_width(int channel_width){
      printf("one\n");
    }


    void set_dram_transaction_granularity(int cacheline_size){
      printf("two\n");
      getchar();
    }
    //output
    one
    two 
    f //keyboard input
    //No more calls 

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

Спасибо

Это результат, который я получаю с GDB **

Для первого кода

(gdb) break mem-dram.c:374
Breakpoint 1 at 0x71c810: file build/ALPHA_FS/mem/dramsim/mem-dram.c, line 374.
(gdb) break mem-dram.c:381
Breakpoint 2 at 0x71c7b0: file build/ALPHA_FS/mem/dramsim/mem-dram.c, line 381.
(gdb) run -d ./tmp/MyBench2/ 
one
f
[Switching to Thread 47368811512112 (LWP 17507)]

Breakpoint 1, set_dram_channel_width (channel_width=64)
(gdb) c
Continuing.
two
one
f

Breakpoint 2, set_dram_transaction_granularity (cacheline_size=64)
(gdb) c
Continuing.

Breakpoint 1, set_dram_channel_width (channel_width=8)
374     void set_dram_channel_width(int channel_width){
(gdb) c
Continuing.
two
one
f

Для второго кода

(gdb) break mem-dram.c:374
Breakpoint 1 at 0x71c7b6: file build/ALPHA_FS/mem/dramsim/mem-dram.c, line 374.
(gdb) break mem-dram.c:380
Breakpoint 2 at 0x71c7f0: file build/ALPHA_FS/mem/dramsim/mem-dram.c, line 380.
(gdb) run
one
two
f
[Switching to Thread 46985688772912 (LWP 17801)]

Breakpoint 1, set_dram_channel_width (channel_width=64)
(gdb) c
Continuing.

Breakpoint 2, set_dram_transaction_granularity (cacheline_size=64)
(gdb) c
Continuing.

Breakpoint 1, set_dram_channel_width (channel_width=8)
(gdb) c
Continuing.

person Eduardo    schedule 22.03.2009    source источник
comment
опубликуйте внешний код, а также   -  person    schedule 23.03.2009
comment
... под чем Нейл подразумевает - нам нужно увидеть main()   -  person slim    schedule 23.03.2009
comment
Вы не предоставили нам информацию, необходимую для того, чтобы помочь вам. В частности, мы не можем видеть основную программу или другой вызывающий код. Непонятно, откуда берется буква «ф» — возможно, это то, что вы вводите с клавиатуры, но нам нужно знать наверняка.   -  person Jonathan Leffler    schedule 23.03.2009
comment
Не могли бы вы показать вызовы функций foo1() и foo2(). Я не понимаю, как два примера выходных данных, которые вы даете, могут быть созданы одной и той же последовательностью вызовов. Также было бы полезно различать то, что вы и то, что выводит программа.   -  person Dale Hagglund    schedule 23.03.2009
comment
... различать то, что вы ВВОДИТЕ, и то, что выводит программа. Извините за опечатку.   -  person Dale Hagglund    schedule 23.03.2009
comment
Я опубликую код через некоторое время, это займет у меня немного времени, потому что это большая программа, и это не мой код.   -  person Eduardo    schedule 23.03.2009
comment
Я надеюсь, что выходных данных gdb достаточно   -  person Eduardo    schedule 23.03.2009
comment
Я начинаю думать, что это какая-то тщательно продуманная шутка.   -  person slim    schedule 23.03.2009
comment
Я хотел бы это шутка, я решил сейчас сделать так, как будто этого никогда не было. И когда у меня будет больше времени, я продолжу исследовать. Мне интересно узнать, почему у меня возникла эта проблема. Спасибо за все   -  person Eduardo    schedule 23.03.2009
comment
После перезаписи становится ясно, что set_dram_channel_width() и set_dram_transaction_granularity() делают больше, чем просто getchar() и printf(). Суть проблемы, безусловно, есть.   -  person slim    schedule 23.03.2009
comment
Есть кое-что, но есть только присваивания глобальным переменным, но, безусловно, проблема должна быть в этом. Я изучу это, когда у меня будет больше времени. Спасибо   -  person Eduardo    schedule 23.03.2009


Ответы (1)


Поскольку вы еще не предоставили внешний код (пока?), вот предположение.

while(some condition) {
    foo1();
    foo2();
}
  • foo1 печатает 'one' и ждет ввода. Вы вводите 'f[enter]'.
  • foo1 потребляет 'f'.
  • foo2 печатает «два», а затем использует [enter] (символ новой строки).
  • Затем вы возвращаетесь к началу, и все повторяется снова.

В вашей второй версии foo1() больше ничего не читает.

So:

  • foo1 печатает 'one'
  • foo2 печатает 'two' и ждет ввода. Вы вводите 'f[enter]'
  • foo2 потребляет 'f'

Единственный оставшийся вопрос — почему он останавливается, когда останавливается. Чтобы помочь вам в этом, нам нужно увидеть, что такое (some condition) на самом деле.

Обратите внимание, что довольно необычно вызывать getchar() без сохранения результата (как в c = getchar();). У вас есть причина для этого?

Одна полезная идиома C:

(void) getchar(); 

Преобразование в void указывает программисту, что он знает, что отбрасывает возвращаемое значение.

person slim    schedule 22.03.2009
comment
Это то, к чему я думал, что он имел в виду, но ждал кода. Без этого это, вероятно, лучшее/самое безопасное предположение. Все рано или поздно забывают, что ENTER == '\n'. Принимать ставки, если какое-то условие != EOF? - person Kyle Walsh; 23.03.2009
comment
Возможно, но ни одна из этих функций не возвращает прочитанный символ. Таким образом, у нас есть много догадок, чтобы выяснить, где этот EOF будет прочитан. - person slim; 23.03.2009
comment
Верно. Это должно быть интересно! - person Kyle Walsh; 23.03.2009
comment
Дело в том, что getchar() просто остановил программу. Дело с одним и двумя было просто, чтобы увидеть порядок вызова. Я разместил вывод gdb, надеюсь, это поможет - person Eduardo; 23.03.2009