I seem to be getting a segmentation fault when I call std::make_unique<uint8_t []>. I'm pretty sure I know where the segmentation fault is occurring because I used gdb; however, I can't figure out how to fix it. Here is the source code with irrelevant parts filtered out.
loader.cc:
#include "loader.h"
... // Other code that would make this post unnecessarily long
Section::Section(Binary& bin, bfd *bfd_h, asection *as) : binary(bin) {
int bfd_flags = bfd_section_flags(as);
const char *secname;
Section::SectionType sectype;
sectype = Section::SectionType::NONE;
if (bfd_flags & SEC_CODE) {
sectype = Section::SectionType::CODE;
} else if (bfd_flags & SEC_DATA) {
sectype = Section::SectionType::DATA;
}
this->type = sectype;
this->vma = bfd_section_vma(as);
this->size = bfd_section_size(as);
secname = bfd_section_name(as);
this->name = std::string { secname != nullptr ? secname : "<unnamed>" };
this->bytes = std::make_unique<uint8_t []>(this->size); // SEGFAULT RIGHT HERE
if (!bfd_get_section_contents(bfd_h, as, this->bytes.get(), 0, this->size)) {
throw std::runtime_error("Failed to read section");
}
}
int Binary::load_binary(std::string& fname) {
int ret;
const bfd_arch_info_type *bfd_info;
std::unique_ptr<bfd, bfd_deleter> bfd_h;
try {
bfd_h = open_bfd(fname);
} catch (bfd_exception& be) {
std::cerr << be.fname() << ": " << be.what() << " (" << be.errormsg() << ")" << std::endl;
goto fail;
}
this->filename = std::string (fname);
this->entry = bfd_get_start_address(bfd_h.get());
this->type_str = std::string (bfd_h->xvec->name);
switch (bfd_h->xvec->flavour) {
case bfd_target_elf_flavour:
this->type = Binary::BinaryType::ELF;
break;
case bfd_target_coff_flavour:
this->type = Binary::BinaryType::PE;
break;
case bfd_target_unknown_flavour:
default:
std::cerr << "unsupported binary type ("
<< bfd_h->xvec->name << ")" << std::endl;
goto fail;
}
bfd_info = bfd_get_arch_info(bfd_h.get());
this->arch_str = std::string{bfd_info->printable_name};
switch (bfd_info->mach) {
case bfd_mach_i386_i386:
this->arch = Binary::BinaryArch::X86;
this->bits = 32;
break;
case bfd_mach_x86_64:
this->arch = Binary::BinaryArch::X86;
this->bits = 64;
break;
default:
std::cerr << "unsupported architecture (" << bfd_info->printable_nameĀ·
<< bfd_info->printable_name << ")" << std::endl;
goto fail;
}
this->load_symbols(bfd_h.get());
this->load_dynsym(bfd_h.get());
if (this->load_sections(bfd_h.get()) < 0) goto fail;
ret = 0;
goto success;
fail:
ret = -1;
success:
return ret;
}
... // Other code that would make this post unnecessarily long
loader.h:
#include <memory>
#include <vector>
#include <bfd.h>
#include <inttype.h>
... // Other code that would make this post unnecessarily long
class Section {
public:
enum class SectionType { NONE, CODE, DATA };
Section(Binary& bin);
Section(Binary& bin, bfd *bfd_h, asection *as);
bool contains(uint64_t addr);
void info();
private:
friend class Binary;
Binary& binary;
std::string name;
SectionType type;
uint64_t vma;
uint64_t size;
std::unique_ptr<uint8_t []> bytes;
};
class Binary {
public:
enum class BinaryType { AUTO, ELF, PE };
enum class BinaryArch { NONE, X86 };
Binary();
Section* get_section_text();
int load_binary(std::string &fname);
void info();
private:
std::string filename;
BinaryType type;
std::string type_str;
BinaryArch arch;
std::string arch_str;
unsigned bits;
uint64_t entry;
std::vector<Section> sections;
std::vector<Symbol> symbols;
int load_symbols(bfd *bfd_h);
int load_dynsym(bfd *bfd_h);
int load_sections(bfd *bfd_h);
... // Other code that would make this post unnecessarily long
};
Here is the backtrace that gdb returned:
(gdb) bt
#0 0x00007fffff335b9f in unlink_chunk (p=p#entry=0x802b7d0, av=0x7fffff46cb80 <main_arena>) at malloc.c:1453
#1 0x00007fffff338881 in _int_malloc (av=av#entry=0x7fffff46cb80 <main_arena>, bytes=bytes#entry=36) at malloc.c:4041 #2 0x00007fffff339a84 in __GI___libc_malloc (bytes=36) at malloc.c:3058
#3 0x00007fffff546045 in operator new(unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4 0x0000000008003b94 in std::make_unique<unsigned char []> (__num=36) at /usr/include/c++/10/bits/unique_ptr.h:966
#5 Section::Section (this=0x7ffffffedd80, bin=..., bfd_h=0x801b730, as=0x801dbf8) at loader.cc:66
#6 0x0000000008003d53 in Binary::load_sections (this=this#entry=0x7ffffffedec0, bfd_h=bfd_h#entry=0x801b730)
at loader.cc:122
#7 0x000000000800487e in Binary::load_binary (this=0x7ffffffedec0, fname=...) at loader.cc:185
#8 0x0000000008002451 in main (argc=<optimized out>, argv=<optimized out>) at loader_demo.cc:13
This code is based on code from "Practical Binary Analysis", so pardon the goto's. I'm also using the bfd library.
TLDR: The book I was using had a function A and another function B that was similar to it. I entered the code into my text editor and wrote the code for function A in my editor. Then I copied and pasted A and modified it into function B. Except that I had forgotten to make one change and that was what was causing the segfault.
I finally found out why my program was segfaulting... kind of. It turns out there was nothing wrong with any code even near make_unique; however, I thought that was the case since the stack trace that gdb output indicated that the error was at make_unique.
The error was actually from copying code. There was a code snippet in the book of a function called load_symbols_bfd. I typed the code into my text editor and modified the code into more modern C++. There was a similar function called load_dynsym_bfd. I figured that I could copy the modified version of load_symbols_bfd and change it into my own version of load_dynsym_bfd. However, I had forgotten to change one of the function names in my modified version of load_dynsym_bfd that had been in load_symbols_bfd; I had forgotten to change bfd_canonicalize_symtab into bfd_canonicalize_dynamic_symtab. When the line containing bfd_canonicalize_symtab was commented out in my modified version of load_dynsym_bfd the segfault disappeared.
Related
This is the class in question (only functions that pertain to this question) and everything it depends on (all written myself). It provides an interface to a DLL.
struct MemRegion {
const uint64_t address;
const uint64_t size;
};
enum Version {
VERSION_US,
VERSION_JP
};
const struct MemRegion SEGMENTS[2][2] = {
{{1302528, 2836576},
{14045184, 4897408}},
{{1294336, 2406112},
{13594624, 4897632}},
};
using Slot = array<vector<uint8_t>, 2>;
class Game {
private:
Version m_version;
HMODULE m_dll;
const MemRegion* m_regions;
public:
Game(Version version, cstr dll_path) {
m_version = version;
m_dll = LoadLibraryA(dll_path);
if (m_dll == NULL) {
unsigned int lastError = GetLastError();
cerr << "Last error is " << lastError << endl;
exit(-2);
}
// this is a custom macro which calls a function in the dll
call_void_fn(m_dll, "sm64_init");
m_regions = SEGMENTS[version];
}
~Game() {
FreeLibrary(m_dll);
}
void advance() {
call_void_fn(m_dll, "sm64_update");
}
Slot alloc_slot() {
Slot buffers = {
vector<uint8_t>(m_regions[0].size),
vector<uint8_t>(m_regions[1].size)
};
return buffers;
}
void save_slot(Slot& slot) {
for (int i = 0; i < 2; i++) {
const MemRegion& region = m_regions[i];
vector<uint8_t>& buffer = slot[i];
cerr << "before memmove for savestate" << endl;
memmove(buffer.data(), reinterpret_cast<void* const>(m_dll + region.address), region.size);
cerr << "after memmove for savestate" << endl;
}
}
};
When I call save_slot(), it should copy two blocks of memory to a couple of vector<uint8_t>s. This does not seem to be the case, though. The function finishes the first copy, but throws a segmentation fault at the second memcpy. Why does it only happen at the second copy, and how can I get around this sort of issue?
Edit 1: This is what GDB gives me when the program terminates:
Thread 1 received signal SIGSEGV, Segmentation fault.
0x00007ffac2164452 in msvcrt!memmove () from C:\Windows\System32\msvcrt.dll
Edit 2: I tried accessing the segments individually. It works, but for some reason, I can't access both segments in the same program.
I found out that HMODULE is equivalent to void*. Since you can't really use pointer arithmetic on void*s, you have to cast it to a uint8_t* or equivalent to properly get an offset.
Here's what that looks like in practice:
void save_state(Slot& slot) {
uint8_t* const _dll = (uint8_t*)((void*)m_dll);
for (int i = 0; i < 2; i++) {
MemRegion segment = m_regions[i];
std::vector<uint8_t>& buffer = slot[i];
memmove(&buffer[0], _dll + segment.address, segment.size);
}
}
I have been using this code for a long time now in a project. However, I have recently added llvm-config --cxxflags --libs to the compiler in order to link with llvm libraries and it started generating seg faults. I have located the error and it happens when I call base class's variables.
Here is a small example of what I a doing
in Literals.hh
class LiteralObj : public RuleObj {
public:
LiteralObj();
LiteralObj(char *str);
~LiteralObj();
std::string raw_value;
static int literalobj_cnt;
int literalobj_id;
};
class LiteralIntObj : public LiteralObj{
public:
LiteralIntObj();
LiteralIntObj(char *str);
~LiteralIntObj();
void graphVis(std::ofstream &ofs, std::string &srcRef);
CODE_GENERATION;
int value;
};
Literals.cc
LiteralObj::LiteralObj() : RuleObj(){
ENTER_STATEMENT
raw_value = "";
literalobj_id = literalobj_cnt;
literalobj_cnt++;
}
LiteralObj::LiteralObj(char *str) : RuleObj(){
ENTER_STATEMENT
std::cerr << ruleobj_id << "\n";
raw_value = str;
literalobj_id = literalobj_cnt;
literalobj_cnt++;
}
LiteralObj::~LiteralObj()
{
ENTER_STATEMENT;
}
LiteralIntObj::LiteralIntObj() : LiteralObj()
{
ENTER_STATEMENT;
value = 0;
}
LiteralIntObj::LiteralIntObj(char *str) : LiteralObj(str)
{
ENTER_STATEMENT;
std::cerr << ruleobj_id << '\n';
value = stoi(raw_value);
}
LiteralIntObj::~LiteralIntObj()
{
ENTER_STATEMENT;
}
void LiteralIntObj::graphVis(std::ofstream &ofs, std::string &srcRef) {
ENTER_GRAPHVIS;
// -- define names
std::string currRef = "LiteralIntObj";
std::string name = "LiteralInt";
std::cerr << raw_value << "\n";
//it crashes here with SEGFAULT.
}
The code prints out raw_value of the base class fine for the first object, but, when the second is called SEGMENTATION Fault is generated.
When i changed compile options the pointers were set to 0xfffffff by default instead of 0. Therefore the check if (pointer) generated true even when the pointer were not initialized that led to calling function graphViz().
I'm having an issue with some C++ code that I'm running. Basically, it works fine with most inputs, but with certain inputs it segfaults after my main function returns. This has been... puzzling. I stopped the run at the segfault to get the stack trace, and it returned this:
#0 malloc_consolidate() at /build/eglibc-oGUzwX/eglibc-2.19/malloc/malloc.c:4151
#1 _int_free() at /build/eglibc-oGUzwX/eglibc-2.19/malloc/malloc.c:4057
#2 boost::re_detail::mem_block_cache::~mem_block_cache()() at /usr/lib/x86_64-linux-gnu/libboost_regex.so.1.54.0
#3 __cxa_finalize() at /build/eglibc-oGUzwX/eglibc-2.19/stdlib/cxa_finalize.c:56
#4 ??() at /usr/lib/x86_64-linux-gnu/libboost_regex.so.1.54.0
#5 ??() at
#6 _dl_fini() at /build/eglibc-oGUzwX/eglibc-2.19/elf/dl-fini.c:252
This made me think that I must be doing something wrong with boost regex, but I can't for the life of me figure it out. The way I'm using regex is that users can input a bunch of strings. Those strings could just be normal text, or they could be regular expressions. Because of this, I basically interact with all the inputs as regular expressions. But what if a user gave a string that was intended as plain text but had a character that could be interpreted differently as a regular expression? What I do is go through all plain text input strings and escape all those characters.
Here's the code that I'm working with. This is my main:
int
main(int argc, char * argv[])
{
// Process input arguments
// The desired input is numVertices (int), graph density (double between 0 and 1), halfLoss (double), total loss (double),
// position expanse (double, m), velocity expanse (double, m/s)
int num_vertices;
double graph_density ;
double half_loss;
double total_loss;
double position_expanse;
double velocity_expanse;
if (argc == 1)
{
num_vertices = 48;
graph_density = 1;
half_loss = 200000;
total_loss = 400000;
position_expanse = 400000;
velocity_expanse = 10000;
}
else
{
if (argc != 7)
{
std::cerr << "Need 6 input arguments" << std::endl;
return 1;
}
std::istringstream ss(argv[1]);
num_vertices;
if (!(ss >> num_vertices))
std::cerr << "First input must be an integer" << std::endl;
graph_density = read_double_input(argv[2]);
half_loss = read_double_input(argv[3]);
total_loss = read_double_input(argv[4]);
position_expanse = read_double_input(argv[5]);
velocity_expanse = read_double_input(argv[6]);
}
// Determine how many edges to create
int num_edges = (int) ( (graph_density * num_vertices * (num_vertices - 1)) + 0.5 );
// Create the edges
int edges_created = 0;
std::set<std::pair<int, int> > edge_set;
while (edge_set.size() < num_edges)
{
// Pick a random start vertex and end vertex
int start_vertex = rand() % num_vertices;
int end_vertex = rand() % num_vertices;
// Make sure the start and end vertices are not equal
while (start_vertex == end_vertex)
{
end_vertex = rand() % num_vertices;
}
// Insert the new edge into our set of edges
edge_set.insert(std::pair<int, int>(start_vertex, end_vertex));
}
// Create connection handler
ConnectionHandler conn_handler;
// Create lists for from and to vertices
std::vector<std::string> from_list;
std::vector<std::string> to_list;
// Add connections to from and to lists
for (std::set<std::pair<int, int> >::const_iterator edge_it = edge_set.begin(), end_it = edge_set.end(); edge_it != end_it; ++edge_it)
{
int start_vertex = edge_it->first;
int end_vertex = edge_it->second;
from_list.push_back("Radio" + int_to_string(start_vertex));
to_list.push_back("Radio" + int_to_string(end_vertex));
}
// Read the list into the connection handler
conn_handler.read_connection_list(true, from_list, to_list);
return 0;
}
This code has this ConnectionHandler object that I created. Here's the header for that:
#ifndef CLCSIM_CONNECTIONHANDLER_HPP_
#define CLCSIM_CONNECTIONHANDLER_HPP_
#include <models/network/NetworkTypes.hpp>
#include <generated/xsd/NetworkModelInterfaceConfig.hpp>
namespace clcsim
{
typedef std::map<std::string, std::set<std::string> > ConnectionFilter;
class ConnectionHandler
{
public:
ConnectionHandler();
~ConnectionHandler();
void read_connection_list(const bool is_white_list, const std::vector<std::string> &from_radios, const std::vector<std::string> &to_radios);
private:
ConnectionFilter filter_;
std::set<std::string> from_list_;
std::set<std::string> to_list_;
bool is_white_list_;
};
} // namespace clcsim
#endif // CLCSIM_CONNECTIONHANDLER_HPP_
And here's the source:
#include <models/network/ConnectionHandler.hpp>
#include <oasis/framework/exceptions/ConfigurationException.h>
#include <boost/regex.hpp>
namespace clcsim
{
ConnectionHandler::
ConnectionHandler()
{
}
ConnectionHandler::
~ConnectionHandler()
{
std::cout << "Destructing conn handler" << std::endl;
}
void
ConnectionHandler::
read_connection_list(
const bool is_white_list,
const std::vector<std::string> &from_radios,
const std::vector<std::string> &to_radios)
{
std::cout << "Reading the connection list" << std::endl;
// Make sure the size of both the input vectors are the same
std::size_t from_radio_size = from_radios.size();
std::size_t to_radio_size = to_radios.size();
if (from_radio_size != to_radio_size)
{
throw ofs::ConfigurationException("Error while initializing the "
"Network model: "
"Connections in from/to lists don't align"
);
}
// Create a regular expression/replacement to find all characters in a non-regular expression
// that would be interpreted as special characters in a regular expression. Replace them with
// escape characters
const boost::regex esc("[.$|()\\[\\]{}*+?\\\\]");
const std::string rep("\\\\&");
// Iterate through the specified connections
for (int i = 0; i < from_radio_size; ++i)
{
std::string from_string = boost::regex_replace(from_radios[i], esc, rep, boost::match_default | boost::format_sed);
std::string to_string = boost::regex_replace(to_radios[i], esc, rep, boost::match_default | boost::format_sed);
//std::cout << "From " << from_string << " to " << to_string << std::endl;
filter_[from_string].insert(to_string);
//filter_[from_radios.at(i)].insert(to_radios.at(i));
}
std::cout << "Got here" << std::endl;
}
} // namespace clcsim
Sorry for so much code.
I saw some similar threads related to segfaults with boost::regex. In those examples, the users had really simple code that just created a regex and matched it and ran into an error. It turned out the issue was related to the Boost versioning. I tried to see if I could replicate those sorts of errors, but those simple examples worked just fine for me. So... I'm pretty stumped. I'd really appreciate any help!
For the sake of removing this from the "Unanswered" list, I'm going to post the answer that was provided in the comments instead of here. The OP determined that the suggestion that Boost linked against eglibc was indeed conflicting with the rest of the code linked against glibc. As such, the OP found that upgrading his OS so that eglibc linked libraries were no longer in use fixed the problem.
I call this code in main()
for (COwnerList l=b1.ListOwners(10); !l.AtEnd(); l.Next())
cout << l.Surname() << ", " << l.Name () << endl;
for (CCarList l=b1.ListCars("Peter","Smith"); !l.AtEnd(); l.Next ())
cout << l.RZ () << ", " << l.VIN() << endl;
for (COwnerList l=b1.ListOwners(10); !l.AtEnd(); l.Next())
cout << l.Surname() << ", " << l.Name() << endl;
I tried to debug and found out seg fault comes from Constructor of COwnerList
COwnerList CRegister::ListOwners (unsigned int vin) const
{
vector<Car>::const_iterator it;
COwnerList tmp;
it = lower_bound(byVINList.begin(), byVINList.end(), Car("",vin), cmpVIN);
if(it != byVINList.end())
tmp.car = &(*it);
tmp.in = it->owners.end() - it->owners.begin();
return tmp;
}
constructor im calling looks like this:
COwnerList::COwnerList(void)
{
here = car->owners.begin();
i = 0;
in = car->owners.end() - car->owners.begin();
}
interesting is it doesnt crash after 1st for in main(), so there must be something wrong in the code between those 2 for cycles in main(), but i have no idea what it could be i am not modifying anything related to ListOwners() there
EDIT1
Car constructor:
Car::Car( const string & pid,
const unsigned int & pvin = 0,
const string & cname = "",
const string & csurname = "")
{
rz = pid;
VIN = pvin;
name = cname;
surname = csurname;
}
EDIT2
class COwnerList
{
public:
COwnerList(void);
string Name ( void ) const;
string Surname ( void ) const;
bool AtEnd ( void ) const;
void Next ( void );
//vector<pair<string, string> > powners;
const Car *car;
int in;
private:
vector<pair<string, string> >::const_iterator here;
int i;
};
The problem is that the car pointer is not initialized during the call in the COwnerList constructor. In the first loop, you might have got lucky. Things like this happens all the time. Sometimes the OS won't throw a seg fault everytime when you are calling a code which is not allocated yet.
Just put a condition guard in your code like this:
if (car != NULL) {
here = car->owners.begin();
i = 0;
in = car->owners.end() - car->owners.begin();
}
The error is more likely you are modifying the vector after saving that tmp.toto pointer to the vector's internal storage.
Note that when you do tmp.car = &(*it) you are making a pointer towards the internal storage of the vector.
If later you call push_back() on the vector, you cannot rely in the pointers that you had before, because the vector can reallocate its contents in other memory addresses after you call the push_* methods.
Also note that a debugger may not tell the exact line that has to be corrected, even if the crash happens there. The debugger may tell you the first line where the problem is evident, but the cause of the problem may have happened several lines before.
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;
};
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.
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?