我们知道,printf
函数只能打印像int,char,char *等POD类型。如果我们传递std::string
类型而不调用它的c_str()
成员函数,然后通过提出ILLEGAL INSTRUCTION
信号来中止该程序。
就像下面的简单代码一样。
#include <iostream>
#include <string>
int main()
{
std::string str("hello world");
printf("%s\n", str);
return 0;
}
如果使用g++ -g
构建它,并设置ulimit -c unlimited
,则在运行程序时,它将在运行时进行核心转储。如果你在核心文件上运行gdb,gdb会告诉你这个程序在行std::string str("hello world");
出错了,非常奇怪。
这是截图。
所以我正在考虑这种现象下的机制。
我知道这可能是一个微不足道的问题,但了解它的机制非常酷。
答案 0 :(得分:2)
当printf
的参数的格式字符串包含%s
并且相应的参数不是char
指向\0
的指针时,程序的行为为{{1 }}
通常undefined
将包含一些包含实际数据信息的指针(开始指针,结束指针/大小等),并且数据可能会或可能不会以空值终止。因此,尝试使用std::string
函数打印std::string
是一种未定义的行为。 (请注意:C
的类型为std::string::c_str
且空终止,因此可以使用const char *
打印
printf
无法在编译时检查参数的有效性,并且它会消耗参数。如果它读取的数据不可读,则可能会实现陷阱实现,或者它可能会崩溃或可能按预期工作。
答案 1 :(得分:1)
C ++ 03标准表示,将不是POD的东西传递给varargs(...)参数是未定义的行为。事实上,gcc会向你发出一个警告,告知程序会崩溃(但无论如何都会成功编译)。
具体来说,这意味着
printf("This doesn't use the arguments", std::string(""));
可能会崩溃。
顺便提一下,在C ++ 11中,这有条件地支持使用实现定义的语义定义的实现,但仍然最好避免&#39;。
没有机制,也没有任何特定行为的保证。它可能崩溃,它可以工作,它可以重新格式化您的硬盘驱动器。看看特定的编译器在做什么真的没什么兴趣。