C++ 如何调试Cygwin故障?
我正在从Centos移植到Cygwin,发现我的应用程序正在退出,没有错误消息,并且在Botan::InitializationVector的构造函数执行期间退出状态为零 如果我尝试在main()中主动附加gdb,而gdb正在等待一个spin变量,则不会得到正常的堆栈跟踪:C++ 如何调试Cygwin故障?,c++,gdb,cygwin,porting,botan,C++,Gdb,Cygwin,Porting,Botan,我正在从Centos移植到Cygwin,发现我的应用程序正在退出,没有错误消息,并且在Botan::InitializationVector的构造函数执行期间退出状态为零 如果我尝试在main()中主动附加gdb,而gdb正在等待一个spin变量,则不会得到正常的堆栈跟踪: (gdb) where #0 0x7c90120f in ntdll!DbgUiConnectToDbg () from /cygdrive/c/WINDOWS/system32/ntdll.dll #1 0x7c
(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";
您可以主动连接gdb,并在失败的构造函数调用之前放置一个断点,然后单步执行。您可以主动连接gdb,并在失败的构造函数调用之前放置一个断点,然后单步执行。Cygwin应用程序是多线程的(例如,一个线程是信号侦听器线程)。在gdb中使用
info threads
查找真正出现故障的线程。Cygwin应用程序是多线程的(例如,一个线程是信号侦听器线程)。使用gdb中的info threads
查找真正出现故障的线程。根据新代码,您违反了,这可能会导致您的问题
通过使用原始指针定义一个类,而不提供正确的复制构造函数(或使其不可访问),您可以打开自己的双自由空间
添加复制构造函数。或者在项目的bug跟踪器上打开一个问题。您使用的是最新版本,对吗?根据新代码,您违反了,这可能会导致您的问题 通过使用原始指针定义一个类,而不提供正确的复制构造函数(或使其不可访问),您可以打开自己的双自由空间
添加复制构造函数。或者在项目的bug跟踪器上打开一个问题。您使用的是最新版本,对吗?我知道您很难提供测试用例,但是如果您绝对确定它存在于Botan::InitializationVector的ctor中,那么该ctor的代码可能会有所帮助。@Thomas Edleson我从调试打印混乱中推断出来它在构造函数中失败。代码都是开源的,我在上面已经包含了一些。@WilliamKF:clog不像cerr那样是unitbuf,所以可能会有你看不到的缓冲输出。试试cerr。但是,如果stderr在终端上,它可能是行缓冲的,这会使它变得没有意义……或者使用
endl
而不是“\n”,因为endl
将刷新流。@Ben Voight添加了endl没有不同的结果。我知道您很难提供测试用例,但如果您绝对确定它存在于Botan::InitializationVector的ctor中,那么该ctor的代码可能会有所帮助。@Thomas Edleson我从调试打印消息推断,它在c中失败onstructor。代码都是开源的,我在上面已经包含了一些。@WilliamKF:clog不像cerr那样是unitbuf,所以可能会有你看不到的缓冲输出。试试cerr。但是,如果stderr在终端上,它可能是行缓冲的,这会使它变得没有意义……或者使用endl
而不是“\n”,因为endl
将刷新流。@Ben Voight添加了endl没有不同的结果。我不清楚,我正在主动连接main()我看到了虚假的堆栈跟踪,无法将spin变量设置为false以继续在gdb中执行。@William:为什么在调试过程中使用spin变量来停止执行?这就是断点的作用。这样我就可以附加到正在运行的进程。我不是从gdb运行,而是从命令行运行,然后再附加,所以我希望代码等待发生附加,然后我清除变量。我不清楚,我正在主动附加main()我看到了虚假的堆栈跟踪,无法将spin变量设置为false以继续在gdb中执行。@William:为什么在调试过程中使用spin变量来停止执行?这就是断点的作用。这样我就可以附加到正在运行的进程。我不是从gdb运行,而是从命令行运行,然后再附加,所以我希望代码等到附加发生,我清除变量。这非常有用!不习惯gdb默认为除主线程之外的其他线程。问题与另一个需要通过编译器指令打包和对齐的类有关:attribute((aligned(1),packed))这与Botan中的某些内容有关吗?如果是的话,他们最好对使用默认对齐和打包之外的其他方式有一个非常好的解释。这非常有用!不习惯gdb默认为除主线程之外的其他方式。问题与需要通过编译器指令打包和对齐的另一个类有关:attribute((aligned(1)),已包装)这与Botan中的某些内容有关吗?如果是的话,他们最好对使用默认对齐和打包之外的其他方法有一个非常好的解释。虽然一般来说是真的,但在本例中,基类有一个隐藏的副本构造函数和运算符=,所以我们这里不讨论这个问题。虽然一般来说是真的,但在本例中,基类有一个隐藏的副本构造函数tructor和operator=,所以我们这里不讨论这个问题。
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);
}
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;
(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}
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;
};