Class type Segmentation Fault - c++

It has been long time I did not use c++ and I have some basic errors. Can you tell me why I get Segmentation Fault from my generic code?
When I use int as a array type, it works perfectly but when I change it with "Trapdoor" type, it gives me Seg Fault.
array<array<int, colN>, rowN> SmartIds::createMatrix() {
array<array<int, colN> , rowN> a;
for(int i = 0; i < rowN; i++) {
a[i] = createTrapdoors();
}
//sort(a.begin(), a.end());
return a;
}
Below code generates seg fault
array<array<Trapdoor, colN>, rowN> SmartIds::createMatrix() {
array<array<Trapdoor, colN> , rowN> a;
for(int i = 0; i < rowN; i++) {
a[i] = createTrapdoors();
}
//sort(a.begin(), a.end());
return a;
}
I call my function like below;
auto i = createMatrix();
Trapdoor.cpp class
#include "Trapdoor.h"
#include <cryptopp/pwdbased.h>
using namespace std;
Trapdoor::Trapdoor() {
// TODO Auto-generated constructor stub
key = nullptr;
seed = nullptr;
iv = nullptr;
counter = 0;
}
Trapdoor::Trapdoor(byte* keyy, byte* ivv) {
key = keyy;
seed = keyy;
iv = ivv;
counter = 0;
}
Trapdoor::~Trapdoor() {
// TODO Auto-generated destructor stub
delete iv;
delete key;
delete seed;
}
void Trapdoor::deriveKeywithCounter() {
SecByteBlock derived(32);
PKCS5_PBKDF2_HMAC<SHA1> kdf;
//kdf.DeriveKey(derived.data(), derived.size(), 0, (byte*)b->data(), sizeof(b), NULL, 0, 100);
memset(iv, 0x00, CryptoPP::AES::DEFAULT_KEYLENGTH);
counter++;
}
int Trapdoor::getCounter() {
return counter;
}

The Trapdoor class does not have a correct copy-constructor or copy-assignment operator. So when objects are copied by value, the old and the new both have destructor called and pointers are freed twice etc. etc.
It's rarely a good design to have your class be calling delete on things that it did not new. Your code needs to be clear about who is responsible for freeing memory.
Usually, the best solution is to code Trapdoor so that it actually does not require any delete at all; then you do not have to write any special functions. See Rule of three/five/zero. (I will update this post to include a code sample if you show your class definition).

Related

Remove the warning C6001

I am using VS2017 and do not understand why I am getting compiler "Warning C6001 Using uninitialized memory 'values'", on line if(values!= NULL) in catch block.
#include <windows.h>
typedef enum
{
VALUE_STATE_NOT_AVAILABLE = 1,
VALUE_STATE_ERROR = 2,
VALUE_STATE_VALID = 3,
VALUE_STATE_UNKNOWN = 4
} XyzValueState_t;
class XyzValue
{
private: XyzValueState_t _valueState;
protected: XyzValue( XyzValueState_t valueState ) {
_valueState = valueState;
}
}
typedef XyzValue* xyzValuePtr_t;
main(){
bool flag=true;
xyzValuePtr_t* values = NULL;
unsigned int _argument=2;
if(flag==true) {
values = new PCLValuePtr_t[2]{ NULL,NULL };
try {
values[0] = new PCLUnsignedInteger(_argument);
values[1] = new PCLUnsignedInteger(_argument);
xyz(values); // passing the value to third party function which returns void
}
catch(...) {
if(values!= NULL){
for(int k = 0; k < 1; k++) {
delete values[k];
values[k] = NULL;
}
delete [] values;
values = NULL;
}
}
}
}
Thank you in advance for your help and guidance
not quite sure why your compiler thinks this might be unitialized.
But, in C++, I'd argue that the way you're building your array with new is unnecessarily complicated and error prone. This look like someone from 1993 tried to write C++11. You have initializer lists, but you don't use RAII!
so, do the C++ thing and use C++'s deterministic object lifetime to manage memory. For an array of objects, this is elegantly handled by std::vector:
#include <vector>
class XyzValue;
main(){
bool flag=true;
unsigned int _argument=2;
if(flag==true) {
std::vector<XyzValue> values(2); // default initialization for two XyzValues.
try {
xyz(values.data()); // if you need the raw contiguous memory. **You probably don't.**
}
catch(...) {
// all the manual deletion not necessary anymore, because at end of scope, things are deconstructed automatically, so this catch clause now is empty.
}
}
}
See how this is much shorter, better readable, has the same functionality, but none of the need to manually delete anything? That's why we write C++ instead of C.

Segfault with std::vector =-operation to uninitialized space

I get segmentation faults when I use the =-operator to copy a struct that contains a std::vector to uninitialized memory.
The critical code looks like that:
template<typename T>
ComponentContainer
{
T* buffer;
size_t capacity;
size_t m_size;
public:
ComponentContainer();
~ComponentContainer();
size_t size();
void resize(size_t size);
T & operator[](size_t index);
};
template<typename T>
void ComponentContainer<T>::resize(size_t newSize)
{
if(this->m_size >= newSize)
{
this->m_size = newSize;
}
else
{
if(this->capacity < newSize)
{
const size_t newCapacity = capacity*2;
T* newBuffer = (T*)malloc(newCapacity*sizeof(T));
for(size_t i = 0; i<m_size; i++)
{
// checks if this->buffer[i] is valid intialized memory
if(pseudo_checkIfElementIsInitialized(i))
{
// when this is uncommented no segfault happens
//new (&newBuffer[i]) T();
newBuffer[i] = this->buffer[i]; // <- segfault happens here
}
}
this->capacity = newCapacity;
free(this->buffer);
this->buffer = newBuffer;
}
this->m_size = newSize;
}
}
The T-type is a struct with a std::vector of structs when I get the segfault.
I suspect that the std::vector =-operator uses somehow the left side variable newBuffer[i] and the segmentation fault happens since newBuffer[i] is not initialized.
Objects will be created only with in-placement new with the function T & operator[](size_t index). The malloc should only allocate the memory without initializing anything.
I tried to write a simple example but that hasn't worked out so well:
#include <iostream>
#include <vector>
struct Hello
{
Hello()
{
std::cout << "constructor" << std::endl;
}
~Hello()
{
std::cout << "destructor" << std::endl;
}
std::vector<double> v = std::vector<double>(1);
};
int main()
{
Hello* buffer = (Hello*)malloc(1*sizeof(Hello));
char* noise = (char*)buffer;
for(size_t i = 0; i<sizeof(Hello); i++)
{
noise[i] = 100;
}
auto tmp = Hello();
tmp.v[0] = 6.6;
//new (&buffer[0]) Hello();
buffer[0] = tmp;
std::cout << buffer[0].v[0] << std::endl;
return 0;
}
It works fine without segfault. I assume that is because the uninitialized memory was just by chance ok for the std::vector =-operation.
So
a) is that theory correct
and if yes
b) how to solve this problem without using a default constructor (T()) for every class that i use as T for my ComponentContainer
Well, yeah. You can't assign to an object that doesn't exist.
Uncomment the line that fixes it!
If you can't default construct, then copy construct:
new (&newBuffer[i]) T(this->buffer[i]);
And if you can't do that, then, well, you know the rest.
The malloc should only allocate the memory without initializing anything.
Is it possible that you've underestimated the weight of this statement? You don't just get memory then decide whether or not to initialise it with some values. You have to actually create objects before using them; this is not optional. You're programming C++, not manipulating bits and bytes on a tape :)

Deleting a dynamically allocated Array of Pairs throwing invalid address error

I have a very curious problem. I have a custom class Set, and a custom class Map (I have to recreate the standard library implementations for a class). In my map class, I create an array of pair<string, Set<string>>. But, when I expand my array of values and re-hash the values, I want to delete my old array. But, Whenever (and wherever in my code...) I try to, I get a Invalid address specified to RtlValidateHeap error. This happens even when the delete call is on the line after my new[] statement.
I have private class variable I call pair<string, Set<string>> *values;. Then in my constructor I do the following.
values = new pair<string, Set<string>>[tableSize];
Then when I got to delete values in a member function it threw the invalid address error. The code is below - I swap newValues, and values, then delete newValues in the reallocate() function. That is where the error is thrown
Node: the map is functioning perfectly. I can hash, store, and recall values without any errors.
Expanded Code:
template<>
class Map<std::string, Set<string>> : public MapInterface<string,Set<string>>{
public:
Map() {
numItems = 0;
tableSize = BonusHashTableSize;
values = new pair<string, Set<string>>[tableSize];
for (int i = 0; i < tableSize; ++i) {
values[i].first = "";
}
};
~Map() {
for (int i = 0; i < tableSize; ++i) {
if (values[i].first != "") {
values[i].second.clear();
}
}
delete[] values;
};
void reallocate() {
tableSize *= 2;
pair<string, Set<string>> *newValues = new pair<string, Set<string>>[tableSize];
for (int i = 0; i < tableSize; ++i) {
newValues[i].first = "";
newValues[i].second = Set<string>();
}
for (int i = 0; i < tableSize / 2; ++i) {
if (values[i].first != "") {
int newIndex = rehash(newValues, values[i].first);
newValues[newIndex].first = values[i].first;
newValues[newIndex].second = values[i].second;
Set<string> test = newValues[newIndex].second;
}
}
std::swap(values, newValues);
delete[] newValues;
//member functions
private:
pair<string, Set<string>> *values;
int tableSize;
int numItems;
};
Remove delete values from constructor. What is the purpose of allocation if you are just going to delete in the next line? And also you are using the deleted memory in the next for loop block.
Since you have deleted it here , it will cause invalid memory access error anywhere else because you are trying to delete already deleted memory location.

C++, Weird behavior of cout when trying to print integers

Im trying to write a class that stores an id and a value in an container class.
Im using an nested class as my data structure.
When im compiling the code sometimes it prints perfectly, sometimes it prints nothing and sometimes it prints half of the data then stops.
When i debug the code the same weird behavior occours, when it fails during debug it throws an error "Map.exe has triggered a breakpoint.", the Error occours in the print method when im using cout.
cmap.h
#pragma once
class CMap
{
public:
CMap();
~CMap();
CMap& Add(int id, int value);
void print() const;
private:
class container
{
public:
~container();
int container_id = 0;
int container_value = 0;
};
container* p_komp_;
int dim_ = -1;
void resize();
};
cmap.cpp
#include "cmap.h"
#include <iostream>
using namespace std;
CMap::CMap()
{
p_komp_ = new container[0];
}
CMap::~CMap()
{
p_komp_ = nullptr;
cout << "destroy cmap";
}
CMap& CMap::Add(int id, int value)
{
resize();
p_komp_[dim_].container_id = id;
p_komp_[dim_].container_value = value;
return *this;
}
void CMap::resize()
{
container* temp_array = new container[++dim_];
if (dim_ == 0)
{
temp_array[0].container_id = p_komp_[0].container_id;
temp_array[0].container_value = p_komp_[0].container_value;
}
for (unsigned i = 0; i < dim_; i++)
{
temp_array[i].container_id = p_komp_[i].container_id;
temp_array[i].container_value = p_komp_[i].container_value;
}
p_komp_ = temp_array;
}
void CMap::print() const
{
for (unsigned i = 0; i <= dim_; i++)
{
cout << p_komp_[i].container_id;
cout << p_komp_[i].container_value;
}
}
CMap::container::~container()
{
cout << "destruct container";
}
Map.cpp
#include "cmap.h"
#include <iostream>
using namespace std;
void main(void)
{
CMap m2;
m2.Add(1, 7);
m2.Add(3, 5);
m2.print();
}
These two things are a possible reason for your problem:
int dim_ = -1;
and
container* temp_array = new container[++dim_];
When you allocate, you increase dim_ from -1 to 0. That is you create a zero-sized "array", where every indexing into it will be out of bounds and lead to undefined behavior.
You also have memory leaks since you never delete[] what you new[]. I didn't look for more problems, but there probably a more.
And an "array" (created at compile-time or through new[]) will have indexes from 0 to size - 1 (inclusive). You seem to think that the "size" you provide is the top index. It's not, it's the number of elements.
It seems to me that you might need to take a few steps back, get a couple of good books to read, and almost start over.

Deleting objects on the heap which store data on the heap

My program has been written using classes from the SDL library.
I have the following class:
class s_group
{
private:
SDL_Surface* image;
unsigned int* F_total;
float* F_length;
SDL_Rect** F;
float* F_current;
unsigned int S_total;
unsigned int S_current;
public:
s_group(void);
virtual ~s_group(void);
bool setup( const char* filename, unsigned int s );
//other member functions
};
Private member pointers each store the location of memory declared on the heap, as allocated by the member function setup.
bool s_group::setup( const char* filename, unsigned int s )
{
s_group::~s_group();//delete already allocated heap memory
if(!load_file(image, filename))
{
image = NULL;
return false;
}
S_total = s;
F = new SDL_Rect*[S_total];
F_total = new unsigned int[S_total];
F_length = new float[S_total];
F_current = new float[S_total];
for(unsigned int index = 0; index < S_total; ++index)
{
F[index] = NULL;
F_total[index] = 0;
F_length[index] = 0.f;
F_current[index] = 0.f;
}
//loop for each array slot and set values of data
return true;
}
Within a large function I create an object of this class on the heap, storing its address in an s_group pointer named sparkle.
s_group* sparkle = new s_group;
sparkle->setup("sparkle_final.png", 1 );
On completion of the function I call delete to reallocate the heap memory. Removing this line solves the problem, however there would then be a memory leak.
delete sparkle;
sparkle = NULL;
This will call the destructor of the class which is where I believe the error occurs due to an internal use of the delete operator.
s_group::~s_group(void)
{
SDL_FreeSurface(image);
image = NULL;
for(unsigned int s = 0; s < S_total; ++s)
{
for(unsigned int f = 0; f < F_total[s]; ++f)
{
F[s][f].x = 0;
F[s][f].y = 0;
F[s][f].w = 0;
F[s][f].h = 0;
}
delete[] F[s];
F[s] = NULL;
}
delete[] F;
F = NULL;
delete[] F_total;
F_total = NULL;
delete[] F_length;
F_length = NULL;
delete[] F_current;
F_current = NULL;
S_total = 0;
S_current = 0;
}
On reaching the delete operator, a dialog box appears stating:
Windows has triggered a breakpoint in Program.exe. This may be due to a corruption of the heap, which indicates a bug in Program.exe or any of the DLLs it has loaded.
How do I delete this object without causing the heap corruption?
From effective C++ Scott Meyers
Item 9: Never call virtual functions during construction or destruction.
You shouldn't call virtual functions during construction or destruction, because the calls won't do what you think, and if they did, you'd still be unhappy. If you're a recovering Java or C# programmer, pay close attention to this Item, because this is a place where those languages zig, while C++ zags.
Actually, even though you should define your destructor, calling it forcibly should be out of the question
I'm unable to compile your code but here goes..
The first thing I noticed was that you called your destructor.. You don't want to do that! Instead, create a release function and call that.
The next thing I noticed is that there is no FRAME variable within the class itself.. so this line:
FRAME = new SDL_Rect*[S_total];
is going to cause a compilation error and your destructor uses FRAME but no such variable exists. I think you meant to change it to F because if not, then this line:
F[index] = NULL;
is undefined behaviour since F is uninitialized..
Also, you never initialized each index of FRAME and so accessing it in the destructor like:
FRAME[s][f].x = 0;
is a no-no.
Again, you call
delete[] F;
F = NULL;
but F has no memory allocated and is uninitialized.
Thus with all the patches I think:
class s_group
{
private:
SDL_Surface* image;
unsigned int* F_total;
float* F_length;
SDL_Rect** FRAME;
float* F_current;
unsigned int S_total;
unsigned int S_current;
void Release();
public:
s_group(void);
virtual ~s_group(void);
bool setup(const char* filename, unsigned int s);
//other member functions
};
bool s_group::setup(const char* filename, unsigned int s)
{
Release();//delete already allocated heap memory
if(!load_file(image, filename))
{
image = NULL;
return false;
}
S_total = s;
FRAME = new SDL_Rect*[S_total];
F_total = new unsigned int[S_total];
F_length = new float[S_total];
F_current = new float[S_total];
for(unsigned int index = 0; index < S_total; ++index)
{
FRAME[index] = NULL;
F_total[index] = 0;
F_length[index] = 0.f;
F_current[index] = 0.f;
}
//loop for each array slot and set values of data
return true;
}
void s_group::Release()
{
SDL_FreeSurface(image);
image = NULL;
for(unsigned int s = 0; s < S_total; ++s)
{
for(unsigned int f = 0; f < F_total[s]; ++f)
{
if (FRAME[s])
{
FRAME[s][f].x = 0;
FRAME[s][f].y = 0;
FRAME[s][f].w = 0;
FRAME[s][f].h = 0;
}
}
delete[] FRAME[s];
FRAME[s] = NULL;
}
delete[] FRAME;
FRAME = NULL;
delete[] F_total;
F_total = NULL;
delete[] F_length;
F_length = NULL;
delete[] F_current;
F_current = NULL;
S_total = 0;
S_current = 0;
}
s_group::~s_group(void)
{
Release();
}
should do it.. Just don't forget to allocate memory for FRAME[index] I wasn't sure how much or what you wanted to allocate so I changed the Release function to check if FRAME[index] is valid with an if-statement
I would strongly advise that you use some SmartPointers and forget about handling every single memory allocation yourself..
Since posting this question I have located the source of the error and solved the issue.
In a separate section of code which set the data values for the dynamic 2D array the loop validation was incorrect.
for( unsigned int index = 0; index <= F_total[ S_current ]; ++index ) {
//set data values for each slot in the array
F[ S_current ][ index ].x = 0; etc...
}
As can be seen the loop will clearly attempt to modify a location equal to the size of the created array. Noting of course that arrays begin at index 0, so the final slot will be at size - 1. Something very silly that I missed when writing the code. Actual loop:
for( unsigned int index = 0; index < F_total[ S_current ]; ++index ) {
//set data values for each slot in the array
F[ S_current ][ index ].x = 0; etc...
}
A message for anyone attempting their own memory management:
Finding the source of heap corruption is difficult as the compiler will locate the error in sections of code which do not necessarily cause the problem.
The cause of the problem will only ever be in the section of your code which is affecting the memory. Ensure that you do not attempt to access or worse modify any memory that you have not been given.
I still believe that memory management is a great way to learn and would rather complete any projects in this way than using containers or smart pointers as recommended. This is my personal preference despite custom memory management often offering very few advantages, only complexities.
When asking for assistance provide all related code on the problem. Although the compiler may direct you to the problem in one section, as I said before, with heap corruption it's not necessarily there.