我正在调试一个应用程序来修复我怀疑是由竞争条件引起的分段错误。
我想在代码中添加一些打印语句,但我知道printf不建议添加对的调用,因为这可能会改变线程的行为并在某些情况下隐藏错误。
查看其他选项,我已经看到使用gdb可以使用断点打印某些内容,然后自动继续执行:
break foo
commands
silent
printf "Called foo: x is %d\n",x
cont
end
Run Code Online (Sandbox Code Playgroud)
这比printf在我的代码中放入一个更好吗?
我知道gdb也有一个跟踪点,但它们只适用于 gdbserver,这是我目前更愿意避免的额外复杂程度。
附加信息:该应用程序是用 C 编写的,可在 Linux 上运行。
在 Python 3.4.3 中,我尝试使用 string.format() 运算符对某些字段进行宽度对齐,它似乎将零长度控制字符与宽度总数进行了计数。示例代码:
ANSI_RED = "\033[31m"
ANSI_DEFAULT="\033[39m\033[49m"
string1 = "12"
string2 = ANSI_RED+"12"+ANSI_DEFAULT
print("foo{:4s}bar".format(string1))
print("foo{:4s}bar".format(string2))
Run Code Online (Sandbox Code Playgroud)
这将输出:
foo12 bar
foo12bar
Run Code Online (Sandbox Code Playgroud)
(第二个输出的“12”为红色,但我无法在 SO 中重现它)
在第二种情况下,我丢失了字段宽度,我假设是因为 Python 看到字符串中的字符总数大于宽度,尽管大多数字符在符合 ANSI 的终端上导致零长度。
拥有 ANSI 颜色和工作字段宽度的干净方法是什么?
如果在printf(1)格式字符串中放入变量,ShellCheck会发出警告。为什么?
是:
printf "$file does not exist\n"
Run Code Online (Sandbox Code Playgroud)
在某些方面不如:
printf "%s does not exist\n" "$file"
Run Code Online (Sandbox Code Playgroud) 我正在修复我继承的遗留项目中的编译器警告。新编译器是 gcc 版本 4.8.5 20150623 (Red Hat 4.8.5-4) (GCC)。
他们有很多代码如下:
#include <cstdio>
#include <cstring>
struct foobar
{
char field1[10];
char field2[5];
};
int main()
{
struct foobar foo;
memset(&foo, ' ', sizeof(foo));
strncpy(foo.field1, "1234567890", sizeof(foo.field1));
// Produces warning
printf("[%.*s]", sizeof(foo.field1), foo.field1);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这会产生警告消息:
1_test.c: In function ‘int main()’:
1_test.c:16:49: warning: field precision specifier ‘.*’ expects argument of type ‘int’, but argument 2 has type ‘long unsigned int’ [-Wformat=]
printf("[%.*s]", sizeof(foo.field1), foo.field1);
Run Code Online (Sandbox Code Playgroud)
这对我来说似乎是错误的,因为 '.*' 应该期待 size_t 但显然它没有......
除了必须执行以下操作之外,还有没有办法在全球范围内解决此问题:
// …Run Code Online (Sandbox Code Playgroud) 对我来说一个持续的烦恼(次要,但不变)是我不能(或不知道如何)在 bash 代码中将字符串拆分为多行。我有的是这个:
while getopts 'd:h' argv; do
case "${argv}" in
d) local target_dir="${OPTARG}" ;;
h)
printf "Usage: remove_file_end_strings [ -d <work directory> ] <string to remove>\n"
return 1
;;
esac
Run Code Online (Sandbox Code Playgroud)
这里看起来不错,因为没有自动换行,但是当限制为 80 个字符并且自动换行时看起来很不整洁。当我想要的是这样的东西时,这在 python 或 ruby 中很简单:
while getopts 'd:h' argv; do
case "${argv}" in
d) local target_dir="${OPTARG}" ;;
h)
printf "Usage: remove_file_end_strings [ -d <work "
"directory> ] <string to remove>\n"
return 1
;;
esac
Run Code Online (Sandbox Code Playgroud)
我的 google-fu 让我失望了,所以有没有办法在 bash 中实现这一点,还是我只需要继续用力咬一块木头?塔
编辑:我刚刚决定了我的次优解决方案:
while getopts 'd:h' argv; do
case "${argv}" …Run Code Online (Sandbox Code Playgroud) 为什么操作符 ( *) 需要访问int*变量的值而不是 for char*?
char *char_ptr;
int *int_ptr;
int mem_size = 50;
char_ptr = (char *) malloc(mem_size);
strcpy(char_ptr, "This is memory is located on the heap.");
printf("char_ptr (%p) --> '%s'\n", char_ptr, char_ptr);
int_ptr = (int *) malloc(12);
*int_ptr = 31337;
printf("int_ptr (%p) --> %d\n", int_ptr, *int_ptr);
Run Code Online (Sandbox Code Playgroud)
输出:
char_ptr (0x8742008) --> 'This is memory is located on the heap.'
int_ptr (0x8742040) --> 31337
Run Code Online (Sandbox Code Playgroud) 我的代码正在读取一个包含整数的文件:3 2 1 2 2 2 3
FILE *fptr;
fptr = fopen(argv[1], "r");
if (fptr == NULL)
{
printf("Cannot open file \n");
exit(0);
}
int c = fgetc(fptr);
printf("%c", c);
fclose(fptr);
Run Code Online (Sandbox Code Playgroud)
这是按预期输出第一个数字 3 但将其用作整数时
printf("%d", c);
Run Code Online (Sandbox Code Playgroud)
它输出 51 吗?我正在尝试将这些数字用作二维数组中计数器和位置的输入。
我在 MCQ 测验中遇到了以下代码,
#include <stdio.h>
int main()
{
int j =2, k =4;
printf(&j["Programming"], &k["Theory"]);
k = j ^ 3;
if (k == j)
printf(&k["Practical"], "Trytosolve");
else
printf(&j["Problem creation"]);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
其中&符号用于开头本身和 printf 语句的引号 ("") 之外。我只知道 printf 语句及其格式说明符的传统用法。我尝试运行此代码,但没有显示错误,但出现此警告:
format not a string literal and no format arguments
和以下输出
ogrammingoblem creation (这是多项选择中的选项之一)
我试图搜索这种用途,但找不到。有人能解释一下 & 和方括号的这种用法吗?
正如这里的多个问题也指出的那样,您可以printf通过将精度设置为要打印的最大长度来格式化未终止的字符串。就像是
printf("%.*s\n", length, str);
Run Code Online (Sandbox Code Playgroud)
将打印length开始于str(或直到第一个 0 字节)的字符。
正如jonathan-leffler在此处指出的,这是由 posix here指定的。在阅读文档时,我发现它实际上从未说明这应该起作用(或者我找不到它),因为“ '%s' 转换会打印一个字符串。 ”和“一个字符串是一个以空字符结尾的字节数组 [ ...] ”。关于精度的注意事项说明“可以指定精度以指示要写入的最大字符数; ”。
我的解释是,上面的行实际上是未定义的行为,但是由于printf的实现是有效的,它不会读取比写入更多的内容。
所以我的问题是:这种解释是否正确?
TLDR:当我尝试兼容 posix 时,我是否应该停止使用这个 printf 技巧,因为存在可能导致缓冲区溢出的实现?
它在 c11/c++ 中使用吗?:
printf("%2$*11$s",...)
Run Code Online (Sandbox Code Playgroud)
它来自一个 elf 文件,这个文件使用 printf() 来操作,就像mem[4]=mem[2]+mem[1]. 你可以参考这个https://ctftime.org/task/5042(这是一个反向 CTF 问题)。
就我而言,我知道 $ 用于指定哪个 var 的位置,但没有引用通知一个块可以有两个 $。
另外,除了位置之外,我在格式中找不到任何关于 $ 的函数。
所以,如果有人能告诉我这是有意义的,我将不胜感激。