字符串错误还是编译器错误?
Posted
技术标签:
【中文标题】字符串错误还是编译器错误?【英文标题】:String Bug or Compiler Bug? 【发布时间】:2019-02-18 21:20:59 【问题描述】:我遇到了以下问题,其中调试中的输出似乎完全违背了代码所说的内容,并且似乎它可能是编译器中的一个错误,除非我遗漏了什么。
下面是代码,它应该创建两个文件名字符串并删除其中一个文件。
auto *real = (base_dir + "/index.txt").c_str();
auto *bkp = (base_dir + "/index.txt.new").c_str();
remove(real);
然而,它在实践中并没有表现出这种行为,实际上我们在 gdb 中得到了以下内容:
auto *real = (base_dir + "/index.txt").c_str();
(gdb) n
auto *bkp = (base_dir + "/index.txt.new").c_str();
(gdb) n
remove(real);
(gdb) p real
$1 = 0x7060e8 "./ss-clientdir/index.txt.new"
(gdb) p bkp
$2 = 0x7060e8 "./ss-clientdir/index.txt.new"
如您所见,尽管字符串是使用具有不同字符串文字的两个不同表达式来初始化的,但在初始化后它们最终会成为指向同一字符串的相同指针。
这是一些编译器优化脱轨还是什么?
【问题讨论】:
记住编程的第一条规则:It's always your fault 欢迎使用 C++。在你打结之前,这里有一些方便的阅读:What is meant by Resource Acquisition is Initialization (RAII)? 这是一些编译器优化脱轨还是什么——除了@Yksisarvinen 的评论,你应该意识到你正在使用的编译器是由全世界有数千人,甚至可能有数百甚至数千家公司。如果您演示的一个小玩具程序中存在这样的编译器错误,那么大多数 C++ 社区都会谈论它并通知编译器编写者(并且对于维护编译器的人来说会很尴尬)。因此,它总是不太可能是编译器错误。 在适当的语言中,这将是一个错误。在 C++ 中,这是“你的错”。 @Boann 我们不要谈论 Java 和适当的语言。 【参考方案1】:auto *real = (base_dir + "/index.txt").c_str();
auto *bkp = (base_dir + "/index.txt.new").c_str();
remove(real);
您在函数调用remove()
中使用real
,但real
指向std::string
内的内部缓冲区,该缓冲区已被销毁,因为它是临时的,尝试从中读取是未定义的行为因此这里唯一的错误是您的代码。
要解决此问题,请保存字符串,然后请求 c_str()
:
auto real = (base_dir + "/index.txt");
auto bkp = (base_dir + "/index.txt.new");
remove(real.c_str());
【讨论】:
以上是关于字符串错误还是编译器错误?的主要内容,如果未能解决你的问题,请参考以下文章
这个深奥的泛型错误是编译器错误还是新限制? (推断类型不符合上限)