-2

私は本「21 世紀 C」 (初版) を読んでいて、文字列の長さやスペースの割り当てに malloc /size を使用せずに、asprintf を使用して文字列を取得する興味深いプログラムを見つけました。文脈を理解するために同書の添付画像を読んでください。以下のプログラムも本から。プログラムのコンパイルが実行され、次のメッセージが表示される代わりに、キーボードからの文字列入力が取得されません。質問: 長い (異常な) エラー メッセージを表示する代わりに、プログラムが keboard からの文字列入力を取得しないのはなぜですか?

#define _GNU_SOURCE  // stdio.h to include asprintf
#include <stdlib.h>
#include <stdio.h>

void get_strings(char const *in) {
    char *cmd;
    asprintf(&cmd, "strings %s", in);
    if (system(cmd))
        fprintf(stderr, "Something went Wrong  %s.\n", cmd);
    free(cmd);
} 

int main(int argc, char **argv) {
    get_strings(argv[0]);   
    //return 0;
}

プログラムを実行すると、出力は次のようになります。

/lib64/ld-linux-x86-64.so.2
libc.so.6
__stack_chk_fail
asprintf
stderr
system
fprintf
__libc_start_main
free
__gmon_start__
GLIBC_2.4
GLIBC_2.2.5
UH-X
AWAVA
AUATL
[]A\A]A^A_
strings %s
Something  went Wrong  %s.
;*3$"
GCC: (Ubuntu 5.3.1-14ubuntu2) 5.3.1 20160413
crtstuff.c
__JCR_LIST__
deregister_tm_clones
__do_global_dtors_aux
completed.7585
__do_global_dtors_aux_fini_array_entry
frame_dummy
__frame_dummy_init_array_entry
get_strings.c
__FRAME_END__
__JCR_END__
__init_array_end
_DYNAMIC
__init_array_start
__GNU_EH_FRAME_HDR
_GLOBAL_OFFSET_TABLE_
__libc_csu_fini
free@@GLIBC_2.2.5
_ITM_deregisterTMCloneTable
_edata
__stack_chk_fail@@GLIBC_2.4
system@@GLIBC_2.2.5
get_strings
__libc_start_main@@GLIBC_2.2.5
__data_start
fprintf@@GLIBC_2.2.5
__gmon_start__
__dso_handle
_IO_stdin_used
__libc_csu_init
__bss_start
asprintf@@GLIBC_2.2.5
main
_Jv_RegisterClasses
__TMC_END__
_ITM_registerTMCloneTable
stderr@@GLIBC_2.2.5
.symtab
.strtab
.shstrtab
.interp
.note.ABI-tag
.note.gnu.build-id
.gnu.hash
.dynsym
.dynstr
.gnu.version
.gnu.version_r
.rela.dyn
.rela.plt
.init
.plt.got
.text
.fini
.rodata
.eh_frame_hdr
.eh_frame
.init_array
.fini_array
.jcr
.dynamic
.got.plt
.data
.bss
.comment


------------------
(program exited with code: 0)
Press return to continue

**I running it on Linux Mint 18. GCC version -5.3.1
Build setting - gcc -Wall   -c "%f"
Compile -       gcc -Wall   -o "%e"   "%f"**

ここに画像の説明を入力

4

2 に答える 2

3

プログラムの目的は、ユーザーからの入力を取得することではありません。system()関数を使用stringsして、独自の名前を唯一の引数としてプログラムを実行します。

Unix 環境で実行している場合、stringsプログラムはファイルをスキャンして印刷可能な文字列を探します。あなたが観察する出力はあまり期待されていません: によって生成された実行可能プログラムにgccは、多くの印刷可能な文字列が含まれています:

  • ソース コードに存在する文字列リテラルを見つけることができます: 何かが間違っていました %s.
  • ロード時に動的に解決される多数のシンボル名
  • ソース ファイルの名前などのデバッグ情報:crtstuff.c
  • で始まるセクション名.
  • いくつかのランダム項目 ( []A\A]A^A_;*3$"...) もあり、これらは実行可能ファイルのコードまたはバイナリ データに存在する印刷可能な文字のシーケンスでありstring、null バイトが続くため、誤って C 文字列として解釈されます。
于 2016-12-28T08:38:25.840 に答える
1

プログラムには、標準入力/キーボードから読み取る場所がありません。そして、コマンドにsystem("strings ...")ファイル名を渡しているため、キーボードからではなく、そのファイルから読み取ります。stringsstrings

プログラムに渡されたファイル名をファイルから読み取る場合は、それargv[0]がプログラム名であることを覚えておく必要があります。などを見る必要がありargv[1]ますargv[2]

for(int i = 1; i < argc; ++i)
    get_strings(argv[i]);
于 2016-12-28T08:24:37.840 に答える