【发布时间】:2021-06-14 22:28:42
【问题描述】:
在我的项目中来自命令行参数的文件名上运行 stat() (perror(): "Bad address") 时,我得到了间歇性奇怪的结果:
// mz.h
class MzImage {
private:
/* ... */
struct Segment {
Dword start, stop, length;
std::string name, type;
Segment(Dword start, Dword stop, Dword length, const std::string &name, const std::string &type) :
start(start), stop(stop), length(length), name(name), type(type) {}
};
std::vector<Segment> segs_;
public:
MzImage(const std::string &path);
// ...
};
// mz.cpp
MzImage::MzImage(const std::string &path) {
cout << "path = " << path << endl;
// ... later, path.c_str() used in stat(), turned out to be NULL
}
// mztool.cpp
int main(int argc, char* argv[]) {
const char* mzfile = argv[1];
cout << "Filename: " << mzfile << endl;
try {
MzImage mz{string(mzfile)};
// ...
}
catch (Error &e) {
cout << "Exception: " << e.what() << endl;
}
return 0;
}
我注意到文件名参数在 main() 中很好,但在 MzImage 的构造函数中为空:
ninja@desktop:~/eaglestrike/mztools$ ./mztool a.exe
Filename: a.exe
path =
在调试器下,进入函数时字符串的值好像消失了:
ninja@desktop:~/eaglestrike/mztools$ gdb ./mztool
(gdb) b MzImage::MzImage
Breakpoint 1 at 0x6512: file mz.cpp, line 43.
(gdb) set args a.exe
(gdb) run
Starting program: /mnt/d/code/EagleStrike/mztools/mztool a.exe
Filename: a.exe
Breakpoint 1, MzImage::MzImage (this=0x7ffffffee100, path="a.exe") at mz.cpp:43
43 MzImage::MzImage(const std::string &path) {
(gdb) p path
$1 = "a.exe"
(gdb) n
44 cout << "path = " << path << endl;
(gdb) p path
$2 = ""
决定在字符串上加个watch,好像被vector构造函数抹杀了?
Breakpoint 1, MzImage::MzImage (this=0x7ffffffee100, path="a.exe") at mz.cpp:43
43 MzImage::MzImage(const std::string &path) {
(gdb) watch -l path
Watchpoint 3: -location path
(gdb) c
Continuing.
Watchpoint 3: -location path
Old value = "a.exe"
New value = <error reading variable: Cannot create a lazy string with address 0x0, and a non-zero length.>
0x000000000800bc8d in std::_Vector_base<MzImage::Segment, std::allocator<MzImage::Segment> >::_Vector_impl::_Vector_impl (this=0x7ffffffee138) at /usr/include/c++/7/bits/ stl_vector.h:89
89 : _Tp_alloc_type(), _M_start(), _M_finish(), _M_end_of_storage()
(gdb) bt
#0 0x000000000800bc8d in std::_Vector_base<MzImage::Segment, std::allocator<MzImage::Segment> >::_Vector_impl::_Vector_impl (this=0x7ffffffee138) at /usr/include/c++/7/bits/ stl_vector.h:89
#1 0x000000000800aba8 in std::_Vector_base<MzImage::Segment, std::allocator<MzImage::Segment> >::_Vector_base (this=0x7ffffffee138) at /usr/include/c++/7/bits/stl_vector.h:127
#2 0x000000000800a228 in std::vector<MzImage::Segment, std::allocator<MzImage::Segment> >::vector (this=0x7ffffffee138) at /usr/include/c++/7/bits/stl_vector.h:263
#3 0x0000000008006547 in MzImage::MzImage (this=0x7ffffffee100, path=<error reading variable: Cannot create a lazy string with address 0x0, and a non-zero length.>) at mz.cpp:43
#4 0x0000000008005d19 in main (argc=2, argv=0x7ffffffee268) at mztool.cpp:22
对可能发生的事情有任何想法吗?这是在 WSL 下运行的 Ubuntu 18.04 上的 g++ 7.5.0。
【问题讨论】:
-
将
-Wshadow添加到您的编译器选项中,然后修复阴影变量的问题。 (stop,start,length,name,type)...例如Segment(Dword _start, Dword _stop, ...,然后是start(_start), stop(_stop), ... -
如果我对这个程序进行一些微不足道的更改,以便它真正为我编译(添加
using Dword = unsigned int;,用const std::exception&替换Exception&,放入一些包含),我不能重现所描述的行为。当我将foo作为命令行参数时,它会打印Filename: foo和path = foo。您可以对其进行编辑以使其成为可重现的示例吗? -
很抱歉没有提供一个最小的例子,我自己在复制它时遇到了问题(见答案),感谢您抽出时间尝试复制它。
标签: c++