如何调试Cygwin失败?
我正在从 Centos 移植到 Cygwin,发现我的应用程序正在退出,没有错误消息,并且在 Botan::InitializationVector 的构造函数期间执行中退出状态为零。
如果我尝试在 main() 中主动附加 gdb,它正在等待自旋变量,我不会得到正常的堆栈跟踪:
(gdb) where
#0 0x7c90120f in ntdll!DbgUiConnectToDbg ()
from /cygdrive/c/WINDOWS/system32/ntdll.dll
#1 0x7c952119 in ntdll!KiIntSystemCall ()
from /cygdrive/c/WINDOWS/system32/ntdll.dll
#2 0x00000005 in ?? ()
#3 0x00000000 in ?? ()
因此,如果没有 gdb,很难找出出了什么问题。
为什么我在 Cygwin 上没有收到错误消息,但应用程序会在执行过程中退出?
我推断它在构造函数内部,因为堵塞仅显示构造函数之前而不是之后的行:
clog << " About to create iv for Botan.\n";
Botan::InitializationVector iv(_rng, size);
clog << " About to copy iv for Botan.\n";
Botan 是开源的: http:// /botan.randombit.net/ 以下是 src/sym_algo/symkey.{h,cpp} 中的一些代码片段:
typedef OctetString InitializationVector;
class BOTAN_DLL OctetString
{
public:
u32bit length() const { return bits.size(); }
SecureVector<byte> bits_of() const { return bits; }
const byte* begin() const { return bits.begin(); }
const byte* end() const { return bits.end(); }
std::string as_string() const;
OctetString& operator^=(const OctetString&);
void set_odd_parity();
void change(const std::string&);
void change(const byte[], u32bit);
void change(const MemoryRegion<byte>& in) { bits = in; }
OctetString(class RandomNumberGenerator&, u32bit len);
OctetString(const std::string& str = "") { change(str); }
OctetString(const byte in[], u32bit len) { change(in, len); }
OctetString(const MemoryRegion<byte>& in) { change(in); }
private:
SecureVector<byte> bits;
};
OctetString::OctetString(RandomNumberGenerator& rng,
u32bit length)
{
bits.create(length);
rng.randomize(bits, length);
}
我将失败的代码移至 main() 中,它工作正常。我还在代码周围放置了 try catch ... ,并且没有抛出任何异常。 main() 和应用程序稍后的故障点之间出现问题。我可以进行分而治之,以缩小它不再起作用的确切点。一位 Botan 开发人员给了我这个精简代码来使用,但也失败了:
Botan::AutoSeeded_RNG _rng;
unsigned int size = 1; // or 16, or 1452 all fail.
Botan::SecureVector<Botan::byte> iv_val(size);
cerr << "We get to here." << endl;
_rng.randomize(&iv_val[0], size);
cerr << "But not here." << endl;
现在我已经让调试器工作了,我看到了 segv:
(gdb) s
Botan::AutoSeeded_RNG::randomize (this=0x1270380, out=0x5841420 "", len=1)
at ../../src/Botan-1.8.11/build/include/botan/auto_rng.h:23
(gdb) s
Program received signal SIGSEGV, Segmentation fault.
0x005d79ee in Botan::AutoSeeded_RNG::randomize (this=0x1270380,
out=0x5841420 "", len=1)
at ../../src/Botan-1.8.11/build/include/botan/auto_rng.h:23
(gdb) p rng
$7 = (class Botan::RandomNumberGenerator *) 0x5841324
(gdb) p *this
$8 = {<Botan::RandomNumberGenerator> = {
_vptr$RandomNumberGenerator = 0x11efc14}, rng = 0x5841324}
(gdb) p *rng
$9 = {_vptr$RandomNumberGenerator = 0x656e6f4e}
这是 auto_rng.h 代码:
class BOTAN_DLL AutoSeeded_RNG : public RandomNumberGenerator
{
public:
void randomize(byte out[], u32bit len)
{ rng->randomize(out, len); } // SEGV on this line.
bool is_seeded() const
{ return rng->is_seeded(); }
void clear() throw() { rng->clear(); }
std::string name() const
{ return "AutoSeeded(" + rng->name() + ")"; }
void reseed(u32bit poll_bits = 256) { rng->reseed(poll_bits); }
void add_entropy_source(EntropySource* es)
{ rng->add_entropy_source(es); }
void add_entropy(const byte in[], u32bit len)
{ rng->add_entropy(in, len); }
AutoSeeded_RNG(u32bit poll_bits = 256);
~AutoSeeded_RNG() { delete rng; }
private:
RandomNumberGenerator* rng;
};
I am porting from Centos to Cygwin and find that my application is exiting with no error message and exit status zero mid execution during the constructor for Botan::InitializationVector.
If I try to attach with gdb proactively in main() where it is waiting on a spin variable, I don't get a normal stack trace:
(gdb) where
#0 0x7c90120f in ntdll!DbgUiConnectToDbg ()
from /cygdrive/c/WINDOWS/system32/ntdll.dll
#1 0x7c952119 in ntdll!KiIntSystemCall ()
from /cygdrive/c/WINDOWS/system32/ntdll.dll
#2 0x00000005 in ?? ()
#3 0x00000000 in ?? ()
So with no gdb, it is hard to figure out what is going wrong.
Why would I get no error message on Cygwin yet the application would exit mid execution?
I deduce it is inside the constructor due to clog only showing for line before and not after constructor:
clog << " About to create iv for Botan.\n";
Botan::InitializationVector iv(_rng, size);
clog << " About to copy iv for Botan.\n";
Botan is open source: http://botan.randombit.net/ Here are some code snippets from src/sym_algo/symkey.{h,cpp}:
typedef OctetString InitializationVector;
class BOTAN_DLL OctetString
{
public:
u32bit length() const { return bits.size(); }
SecureVector<byte> bits_of() const { return bits; }
const byte* begin() const { return bits.begin(); }
const byte* end() const { return bits.end(); }
std::string as_string() const;
OctetString& operator^=(const OctetString&);
void set_odd_parity();
void change(const std::string&);
void change(const byte[], u32bit);
void change(const MemoryRegion<byte>& in) { bits = in; }
OctetString(class RandomNumberGenerator&, u32bit len);
OctetString(const std::string& str = "") { change(str); }
OctetString(const byte in[], u32bit len) { change(in, len); }
OctetString(const MemoryRegion<byte>& in) { change(in); }
private:
SecureVector<byte> bits;
};
OctetString::OctetString(RandomNumberGenerator& rng,
u32bit length)
{
bits.create(length);
rng.randomize(bits, length);
}
I moved the failing code into main() and it works fine. I also put a try catch ... around the code and no exceptions are being thrown. Something goes wrong between main() and the point of failure later in the application. I can do a divide and conquer to narrow down the exact point where it no longer works. One of the Botan developers gave me this stripped down code to use instead that also fails:
Botan::AutoSeeded_RNG _rng;
unsigned int size = 1; // or 16, or 1452 all fail.
Botan::SecureVector<Botan::byte> iv_val(size);
cerr << "We get to here." << endl;
_rng.randomize(&iv_val[0], size);
cerr << "But not here." << endl;
Now that I have the debugger working I see segv:
(gdb) s
Botan::AutoSeeded_RNG::randomize (this=0x1270380, out=0x5841420 "", len=1)
at ../../src/Botan-1.8.11/build/include/botan/auto_rng.h:23
(gdb) s
Program received signal SIGSEGV, Segmentation fault.
0x005d79ee in Botan::AutoSeeded_RNG::randomize (this=0x1270380,
out=0x5841420 "", len=1)
at ../../src/Botan-1.8.11/build/include/botan/auto_rng.h:23
(gdb) p rng
$7 = (class Botan::RandomNumberGenerator *) 0x5841324
(gdb) p *this
$8 = {<Botan::RandomNumberGenerator> = {
_vptr$RandomNumberGenerator = 0x11efc14}, rng = 0x5841324}
(gdb) p *rng
$9 = {_vptr$RandomNumberGenerator = 0x656e6f4e}
Here is auto_rng.h code:
class BOTAN_DLL AutoSeeded_RNG : public RandomNumberGenerator
{
public:
void randomize(byte out[], u32bit len)
{ rng->randomize(out, len); } // SEGV on this line.
bool is_seeded() const
{ return rng->is_seeded(); }
void clear() throw() { rng->clear(); }
std::string name() const
{ return "AutoSeeded(" + rng->name() + ")"; }
void reseed(u32bit poll_bits = 256) { rng->reseed(poll_bits); }
void add_entropy_source(EntropySource* es)
{ rng->add_entropy_source(es); }
void add_entropy(const byte in[], u32bit len)
{ rng->add_entropy(in, len); }
AutoSeeded_RNG(u32bit poll_bits = 256);
~AutoSeeded_RNG() { delete rng; }
private:
RandomNumberGenerator* rng;
};
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
Cygwin 应用程序是多线程的(例如,一个线程是信号侦听器线程)。使用 gdb 中的
infothreads
来查找真正发生故障的线程。Cygwin apps are multithreaded (e.g., one thread is the signal listener thread). Use
info threads
in gdb to find the thread that really faulted.您可以主动附加 gdb,并在失败的构造函数调用之前放置一个断点,然后单步执行。
You could attach gdb proactively and put a breakpoint right before the constructor call that is failing, then single step through.
根据新代码,您违反了三法则,并且可能会导致您的问题。
通过使用原始指针定义一个类并且不提供正确的复制构造函数(或使其不可访问),您将面临双重释放。
添加复制构造函数。或者在项目的错误跟踪器上提出问题。您使用的是最新版本,对吧?
Based on the new code, you're violating the Rule of Three and this may be causing your problem.
By defining a class with raw pointers and not providing a correct copy constructor (or making it inaccessible) you open yourself up to double-free.
Add the copy constructor. Or open an issue on the project's bug tracker. You are using the latest version, right?