C++ 当不正确地打印std::string时,引擎盖下的内存和cpu中发生了什么?
我们知道,C++ 当不正确地打印std::string时,引擎盖下的内存和cpu中发生了什么?,c++,string,printf,C++,String,Printf,我们知道,printf函数只能打印int、char、char*等POD类型,如果我们传递std::string类型而不调用其c_str()成员函数,那么程序将通过发出非法指令信号而中止 就像下面的简单代码一样 #include <iostream> #include <string> int main() { std::string str("hello world"); printf("%s\n", str); return 0; } #包括
printf
函数只能打印int、char、char*等POD类型,如果我们传递std::string
类型而不调用其c_str()
成员函数,那么程序将通过发出非法指令
信号而中止
就像下面的简单代码一样
#include <iostream>
#include <string>
int main()
{
std::string str("hello world");
printf("%s\n", str);
return 0;
}
#包括
#包括
int main()
{
std::string str(“hello world”);
printf(“%s\n”,str);
返回0;
}
如果您使用g++-g
构建它,并设置ulimit-c unlimited
,当您运行程序时,它将在运行时转储内核。如果在核心文件上运行gdb,gdb会告诉您该程序在第std::string str(“hello world”)行出错代码>,很奇怪。
这是截图。
因此,我正在考虑这种现象下的机制
printf如何引发非法指令?像std::字符串内存组合、cpu非法指令等
为什么gdb在代码的上一行声明出错,而不是在printf行
我知道这可能是一个很小的问题,但是理解它的机制是很酷的。当printf
的参数格式字符串包含%s
并且相应的参数不是指向以\0
结尾的字符的指针时,程序的行为是未定义的
通常std::string
将包含一些指针,其中包含实际数据的信息(起始指针、结束指针/大小等),数据可能以null结尾,也可能不以null结尾。因此,尝试使用C
函数打印std::string
是一种未定义的行为。(注意:std::string::c_str
的类型是const char*
并以null结尾,因此可以使用printf
打印)
printf
无法在编译时检查参数的有效性,它会使用参数。如果它读取的数据不可读,陷阱实现可能会被实现,也可能会崩溃或按预期工作。C++03标准表示,将非POD的内容传递给varargs(…)参数是未定义的行为。事实上,gcc会警告您程序将崩溃(但无论如何编译成功)
具体来说,这意味着
printf("This doesn't use the arguments", std::string(""));
可能会崩溃
顺便说一句,在C++11中,用实现定义的语义定义的实现有条件地支持这一点,但仍然在“最好避免”下
没有任何机制,也不能保证任何特定的行为。它可能会崩溃,可能会工作,可能会重新格式化你的硬盘。查看特定编译器正在执行的操作真的不有趣。将在运行时进行核心处理
请从了解核心转储实际上是什么开始,而不是使用“to core”作为动词。并且printfs不会在stackptr处“引发非法指令”@其中是函数指针。。。而且这种行为只是UB,不能保证有任何特定的错误。会吗?我在不久的将来会看到鼻魔。@richard.g正如我刚才对stackptr所说的,不能保证有任何特定的错误。任何事情都有可能发生。有时它甚至可以正常工作。忽略警告通常是个坏主意,尤其是在警告很多的情况下。不能在C中打印std::字符串。C没有std::string@TomTanner你是对的。我的观点是使用C标准函数。让我重新解释一下。@MohitJain有关于“程序行为未定义”部分的文档吗?