asprintf - 如何在 C 中获取字符串输入
asprintf - how to get string input in C
我正在看书《21世纪C》(第一版),发现一个有趣的程序使用asprintf
在不使用 malloc /size of 字符串长度或 space 分配的情况下获取字符串。请阅读同一本书中的附加图片,以了解书中的 context.Following 程序。该程序编译 运行 并且不从键盘输入字符串而是得到以下消息。问题是:为什么程序不从 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"**
您的程序中没有从标准 input/keyboard 读取的地方。 system("strings ...")
将文件名传递给 strings
命令,因此 strings
从该文件而不是键盘读取。
如果您打算使用传递给您的程序的文件名读取文件,您需要记住 argv[0]
是程序名称。你需要看看argv[1]
、argv[2]
等等
for(int i = 1; i < argc; ++i)
get_strings(argv[i]);
该程序的目的不是从用户那里获取输入:它使用 system()
函数来 运行 strings
程序以其自己的名称作为唯一参数。
如果您运行正在 Unix 环境中运行,strings
程序会扫描文件中的可打印字符串。您观察到的输出或多或少出乎意料:由 gcc
生成的程序可执行文件包含许多可打印字符串:
- 您可以发现源代码中存在的字符串文字:
%s 出错了。
- 许多符号名称在加载时动态解析
- 调试信息,如源文件名:
crtstuff.c
- 部分名称以
.
开头
- 还有一些随机项(
[]A\A]A^A_
、;*3$"
...)只是可执行文件代码或二进制数据中存在的可打印字符序列,被 [=18 错误解释=] 作为 C 字符串,因为它们后跟一个空字节。
我正在看书《21世纪C》(第一版),发现一个有趣的程序使用asprintf 在不使用 malloc /size of 字符串长度或 space 分配的情况下获取字符串。请阅读同一本书中的附加图片,以了解书中的 context.Following 程序。该程序编译 运行 并且不从键盘输入字符串而是得到以下消息。问题是:为什么程序不从 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"**
您的程序中没有从标准 input/keyboard 读取的地方。 system("strings ...")
将文件名传递给 strings
命令,因此 strings
从该文件而不是键盘读取。
如果您打算使用传递给您的程序的文件名读取文件,您需要记住 argv[0]
是程序名称。你需要看看argv[1]
、argv[2]
等等
for(int i = 1; i < argc; ++i)
get_strings(argv[i]);
该程序的目的不是从用户那里获取输入:它使用 system()
函数来 运行 strings
程序以其自己的名称作为唯一参数。
如果您运行正在 Unix 环境中运行,strings
程序会扫描文件中的可打印字符串。您观察到的输出或多或少出乎意料:由 gcc
生成的程序可执行文件包含许多可打印字符串:
- 您可以发现源代码中存在的字符串文字: %s 出错了。
- 许多符号名称在加载时动态解析
- 调试信息,如源文件名:
crtstuff.c
- 部分名称以
.
开头
- 还有一些随机项(
[]A\A]A^A_
、;*3$"
...)只是可执行文件代码或二进制数据中存在的可打印字符序列,被 [=18 错误解释=] 作为 C 字符串,因为它们后跟一个空字节。