リダイレクトは正しいです。問題は生成しているアセンブリ内になければなりません。
このような問題をデバッグするツールはstrace
です。あなたは明確に所望の出力を見ることができます
strace ./basic
...
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa5bb8da000
write(1, "10\n", 3) = 3
10
write(1, "z\377n\f\377\177\0\0\0\0\0\0\0\0\0\0\202\377n\f\377\177\0\0\362\377n\f\377\177\0\0"..., 139905561665008 <unfinished ... exit status 0>
、だけでなく、いくつかの「迷」書き込み:strace
の下であなたのプログラムを実行し、表示されます。その書き込みはどこから来ますか?救助へ
GDB:
gdb -q ./basic
Reading symbols from /tmp/basic...done.
(gdb) catch syscall write
Catchpoint 1 (syscall 'write' [1])
(gdb) r
Catchpoint 1 (call to syscall 'write'), 0x00007ffff7b32500 in __write_nocancel()
(gdb) bt
#0 0x00007ffff7b32500 in __write_nocancel() at ../sysdeps/unix/syscall-template.S:82
#1 0x00007ffff7acd133 in _IO_new_file_write (f=0x7ffff7dd7780, data=0x7ffff7ff8000, n=3) at fileops.c:1276
#2 0x00007ffff7ace785 in new_do_write (fp=0x7ffff7dd7780, data=0x7ffff7ff8000 "10\n", to_do=3) at fileops.c:530
#3 _IO_new_do_write (fp=0x7ffff7dd7780, data=0x7ffff7ff8000 "10\n", to_do=3) at fileops.c:503
#4 0x00007ffff7accd9e in _IO_new_file_xsputn (f=0x7ffff7dd7780, data=0x601023, n=1) at fileops.c:1358
#5 0x00007ffff7a9f9c8 in _IO_vfprintf_internal (s=0x7ffff7dd7780, format=<value optimized out>, ap=0x7fffffffda20) at vfprintf.c:1644
#6 0x00007ffff7aaa53a in __printf (format=0x7ffff7ff8000 "10\n") at printf.c:35
#7 0x000000000040054f in main()
良い、これは書くことが期待呼び出しです。
(gdb) c
10
Catchpoint 1 (returned from syscall 'write'), 0x00007ffff7b32500 in __write_nocancel() at ../sysdeps/unix/syscall-template.S:82
82 in ../sysdeps/unix/syscall-template.S
これはsyscallからの単なる戻り値です。書き込みは成功しましたか? (上記の出力を確認したのでわかりましたが、確認してください)
(gdb) p $rax
$1 = 3
良い。書き込みは予想された3文字を書きました。
(gdb) c
Catchpoint 1 (call to syscall 'write'), 0x0000000000400577 in os_return()
これは私たちが期待していなかった書き込みです。どこから?
(gdb) bt
#0 0x0000000000400577 in os_return()
#1 0x0000000000400557 in main()
(gdb) disas
Dump of assembler code for function os_return:
0x0000000000400557 <+0>: movabs $0x1,%rax
0x0000000000400561 <+10>: movabs $0x0,%rbx
0x000000000040056b <+20>: movabs $0x5,%rcx
0x0000000000400575 <+30>: int $0x80
=> 0x0000000000400577 <+32>: nop
0x0000000000400578 <+33>: nop
0x0000000000400579 <+34>: nop
0x000000000040057a <+35>: nop
0x000000000040057b <+36>: nop
0x000000000040057c <+37>: nop
0x000000000040057d <+38>: nop
0x000000000040057e <+39>: nop
0x000000000040057f <+40>: nop
End of assembler dump.
(gdb) quit
だからあなたのシステムコールは、write(2)
を実行する代わりにexit(2)
を期待します。なぜこれが起こったのですか?
あなたは間違ってEXIT
を定義したので:
grep 'define .*NR_exit' /usr/include/asm/unistd*.h
/usr/include/asm/unistd_32.h:#define __NR_exit 1
/usr/include/asm/unistd_32.h:#define __NR_exit_group 252
/usr/include/asm/unistd_64.h:#define __NR_exit 60
/usr/include/asm/unistd_64.h:#define __NR_exit_group 231
以上のことから、あなたはEXIT
は、64ビットモードで32ビットモードでは1が、60であることを伝えることができます。
NR_writeはどうですか? 64ビットモードで1ですか?
grep 'define .*NR_write' /usr/include/asm/unistd_64.h
#define __NR_write 1
#define __NR_writev 20
実際にはそうです。だから私たちは "どこから迷いが出てきたのですか"という問題を解決しました。パズル。 60であることをEXIT
を固定し、strace
の下で再実行、我々は今、次を参照してください。
...
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa5bb8da000
write(1, "10\n", 3) = 3
10
_exit(1) = ?
まだ右されていないこと。 でなく、_exit(1)
としてください。 x86_64
ABIを見て、自分のレジスタの使用が誤っていることが明らかになった:
はそれを修正(および偽mov rcx, 5
を削除)など、システムコール番号は%rax
にする必要がありますが、%rdi
で引数、%rsi
、%rdx
、我々は最終的に取得しますstrace
から所望の出力:
...
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa5bb8da000
write(1, "10\n", 3) = 3
10
_exit(0) = ?
ので今我々は上記の修正はまた、リダイレクトの問題を修正かどうかを確認する準備が整いました。
再実行リダイレクトされた出力と、straceの下:
strace ./basic > t
...
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f08161eb000
_exit(0) = ?
明らかにwrite
への私たちのコールが欠落しています。それはどこに行きましたか?
よく、stdout
の出力はデフォルトで行バッファリングされ、ファイルにリダイレクトされると完全にバッファリングされます。おそらくfflush
コールがありませんか?
確かに、ちょうど終了する前にfflush(NULL)
への呼び出しを追加することで問題を解決:
...
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f8afd450000
write(1, "10\n", 3) = 3
_exit(0) = ?
私はあなたが上で適切に入力をリダイレクトしている今日(私は;-)
をした何かを学んだ願っていますコンソール。アセンブリがstd outに印刷されていることを確認しましたか? – VolatileDream
'./basic | 'を実行すると、画面には何が表示されますか?猫? –
John - ./basic |猫はまだ何も返さない Jex - 私はprintfのドキュメントを見て、それがstdoutに印刷すると言います。 –