How can I prevent segmentation faults in my program? - list

I have a C assignment. It is a lot longer than the code shown below, and we are given the function prototypes and instructions only. I have done my best at writing code, but I am stuck with segmentation faults. When I compile and run the program below on Linux, at "735 NaN" it will terminate, indicating a segfault occurred. Why? What am I doing wrong? Basically, the program does not let me access table->list_array[735]->value and table->list_array[735]->key. This is of course the first segfault. There might be more following index 735.
#include <stdio.h>
#include <stdlib.h>
typedef struct list_node list_node_t;
struct list_node
{
char *key;
int value;
list_node_t *next;
};
typedef struct count_table count_table_t;
struct count_table {
int size;
list_node_t **list_array;
};
count_table_t* table_allocate(int size)
{
count_table_t *ptr = malloc(sizeof(count_table_t));
ptr->size = size;
list_node_t *nodes[size];
int k;
for(k=0; k<size; k++){
nodes[k] = NULL;
}
ptr->list_array = nodes;
return ptr;
}
void table_addvalue(count_table_t *table)
{
int i;
for(i=0; i<table->size; i++)
{
table->list_array[i] = malloc(sizeof(list_node_t));
table->list_array[i]->value = i;
table->list_array[i]->key = "NaN";
table->list_array[i]->next = NULL;
}
}
int main()
{
count_table_t *table = table_allocate(1000);
table_addvalue(table);
int i;
for(i=0; i<table->size; i++)
printf("%d %s\n", table->list_array[i]->value, table->list_array[i]->key);
return 0;
}

You're point ptr->list_array at a local variable (nodes) in table_allocate, which goes away when that function returns, leaving a dangling pointer. You probably want
list_node_t **nodes = malloc(size * sizeof(list_node_t *));

I recommend the routine use of valgrind(1) to prevent such problems from occurring.

Related

How to return a pointer to a ragged array through a function argument?

I need to modifiy an existing API and basically the only option I have is returning a pointer to a ragged array through a function argument (this would normally not be me personal preference). I can't get my head around doing this and keep getting a segmentation fault at this part of the code:
void getMxByArg(int ***pppX) {
*pppX = m_ppMx; // SEGMENTATION FAULT HERE
}
I've provided an example below which doesn't have any external dependencies and encapsulates the problem.
#include <stdint.h>
#include <iostream>
using namespace std;
class Mx {
public:
Mx() {
int *buff01 = (int*)malloc(3 * sizeof(int));
int *buff02 = (int*)malloc(3 * sizeof(int));
buff01[0] = 0;
buff01[1] = 1;
buff01[2] = 3;
buff02[0] = 4;
buff02[1] = 5;
buff02[2] = 6;
m_n = 2;
m_ppMx = (int**)malloc(m_n * sizeof(int*));
m_ppMx[0] = buff01;
m_ppMx[1] = buff02;
}
~Mx() {
for (int i=0; i<m_n; ++i) {
free(m_ppMx[i]);
}
free(m_ppMx);
}
int** getMx() {
return m_ppMx;
}
void getMxByArg(int ***pppX) {
*pppX = m_ppMx; // SEGMENTATION FAULT HERE
}
private:
int **m_ppMx;
int m_n;
};
int main()
{
Mx mx;
// SUCCESS
int **ppX = mx.getMx();
// FAILURE, Results in segmentation fault in getMxByArg
int ***pppX;
mx.getMxByArg(pppX);
return 0;
}
In the posted code, you are dereferencing an uninitialized pointer. That's cause for undefined behavior.
The solution is:
Create a variable of type int**.
Pass the address of that variable to the function.
int **ppX2;
mx.getMxByArg(&ppX2);
Another option is to change the argument type to int**&.
void getMxByArg(int**& ppX) {
ppX = m_ppMx;
}
Then, you can use:
int **ppX2;
mx.getMxByArg(ppX2);

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.

SIGSEGV error occurs in implementation of a hash table in C++

I am trying to implement a hash table data structure in C++, but every time i run the program i get a run time error(SIGSEGV, segmentation fault) in line number 86 like here.
i.e.: putInHash(str,hashTable,m); in main().
This is my code:
#include <iostream>
#include<string.h>
#include<math.h>
#include<stdlib.h>
using namespace std;
typedef struct node
{
struct node *next,*prev;
string data;
}node;
int hashCode(string str)
{
char arr[str.size()+1];
strcpy(arr,str.c_str());
int code=0;
for(int i=0;i<str.size();i++)
{
code+=((i+1)*((int)arr[i]));
}
return code;
}
int compress(int k,int m)
{
double a=(sqrt(5.0)-1)/2;
return floor(m*(fmod(k*a,1)));
}
void display(node* hashTable[],int m)
{
for(int i=0;i<m;i++)
{
cout<<i<<":\n";
node* p=hashTable[i];
while(p!=NULL)
{
cout<<p->data<<" , ";
}
cout<<"\n";
}
}
void putInHash(string str,node* hashTable[],int m)
{
int k=hashCode(str);
int bucket=compress(k,m);
if(hashTable[bucket]==NULL)
{
hashTable[bucket]=(node*)malloc(sizeof(node));
hashTable[bucket]->prev=NULL;
hashTable[bucket]->next=NULL;
hashTable[bucket]->data=str;
}
else
{
node* temp=(node*)malloc(sizeof(node));
temp->data=str;
temp->next=hashTable[bucket];
hashTable[bucket]->prev=temp;
temp->prev=NULL;
hashTable[bucket]=temp;
}
}
int main()
{
cout<<"Enter number of strings to add in hash table: ";
long int n;
cin>>n;
cout<<"\n";
int m=13;
node* hashTable[m];
for(int i=0;i<m;i++)
{
hashTable[i]=NULL;
}
string str;
cout<<"Enter the strings:\n";
for(int i=0;i<n;i++)
{
cin>>str;
putInHash(str,hashTable,m);
}
display(hashTable,m);
return 0;
}
I thought it might be due to passing the string, but it turned out this wasn't the case.
Can somebody please guide me through it.
I think the error may be in passing the hashTable[] as an argument.
I can't reproduce your problem (I'm using clang++ in a Linux platform and I suppose that your problem is platform dependent) but I see something that can explain it.
You use malloc() to allocate memory for a struct with a std::string in it.
This is bad.
Really, really bad.
Because malloc() can allocate the memory but can't construct the data member in it.
In C++ you should use new; at least, allocating not trivial objects (std::string isn't trivial).
// node* temp=(node*)malloc(sizeof(node)); // DANGEROUS
node * temp = new node;
This is the problem that cause the sigsegv (I suppose) but your code has a lot of other problem.
Example: the while in display() goes in loop because p remain unchanged; you should change display() in this way
void display (node * hashTable[], int m)
{
node * p;
for(int i=0;i<m;i++)
{
cout << i << ":\n";
for ( p = hashTable[i] ; p ; p = p->next )
cout << p->data << " , ";
cout << "\n";
}
}
Another important point: variable length arrays isn't C++; it's C (C99). So this lines are wrong
char arr[str.size()+1];
node* hashTable[m];
You don't need the first (absolutely useless) and you can simplify hashcode() in this way (and please, pass the strings by const reference, when possible)
int hashCode (const string & str)
{
int code = 0;
for ( int i = 0 ; i < str.size() ; ++i )
code += (i+1) * int(str[i]);
return code;
}
About hashTable, you can substitute it with a std::vector
// node* hashTable[m]; no C++
//for(int i=0;i<m;i++) // useless
//{ // useless
// hashTable[i]=NULL; // useless
//} // useless
std::vector<node *> hashTable(m, NULL); // m NULL node pointers
Obviously, putInHash() should be
void putInHash (string str, std::vector<node*> & hashTable, int m)
and display()
void display (const std::vector<node*> & hashTable, int m)
And remember to free the allocated memory.
p.s.: sorry for my bad English.
--- EDIT ---
phonetagger is right: deleting the memory (a vector o linked nodes) isn't trivial.
I suggest a function like the following
void recursiveFreeNode (node * & nd)
{
if ( nd )
{
recursiveFreeNode(nd->next);
delete nd; // added with EDIT 2; sorry
nd = NULL; // useless, in this, case, but good practice
}
}
and call it (for every node of the vector) in main(), after display() calling
for ( unsigned ui = 0U ; ui < hashTable.size() ; ++ui )
recursiveFreeNode(hashTable[ui]);
--- EDIT 2 ---
Sorry: I've forgot the more important line: delete node (thanks phonetagger).
Following the other suggestion of phonetagger, I propose a not-recursive function for deleting the hashtable's node
void loopFreeNode (node * & nd)
{
node * tmp;
for ( ; nd ; nd = tmp )
{
tmp = nd->next;
delete nd;
}
nd = NULL;
}
Obviously the for loop, to use loopFreeNode(), should be
for ( unsigned ui = 0U ; ui < hashTable.size() ; ++ui )
loopFreeNode(hashTable[ui]);

Can anyone please tell me why is it showing "runtime error"?

I'm trying to implement hash table, but I'm getting a runtime error in the for loop of createHashTable() function. Can anyone please tell me why is it showing this "runtime error"? Is it StackOverflow error?
#include <iostream>
using namespace std;
#define LOAD_FACTOR 20
struct ListNode{
int data;
struct ListNode *next;
};
struct HashTableNode{
int bCount; // number of elements in the block
struct ListNode *next;
};
struct HashTable{
int tSize; // table size
int count; // total number of elements in the table
struct HashTableNode **hashTableNodeArray;
};
int hashFunction(struct HashTable *h, int data){
return data % h->tSize;
}
struct HashTable * createHashTable(int numberOfElements){
struct HashTable *h = new HashTable;
h->count = 0;
h->tSize = numberOfElements / LOAD_FACTOR;
h->hashTableNodeArray = new HashTableNode *[h->tSize];
for(int i = 0; i < h->tSize; ++i){
// this is where it is showing runtime error
h->hashTableNodeArray[i]->bCount = 0;
h->hashTableNodeArray[i]->next = nullptr;
}
return h;
}
void deleteHashTable(struct HashTable *h){
struct ListNode *node, *tmp;
for(int i = 0; i < h->tSize; ++i){
node = h->hashTableNodeArray[i]->next;
while(node != nullptr){
tmp = node;
node = node->next;
delete tmp;
}
}
delete[] h->hashTableNodeArray;
delete h;
}
int main(int argc, char **argv){
struct HashTable *h = createHashTable(220);
deleteHashTable(h);
return 0;
}
h->hashTableNodeArray = new HashTableNode *[h->tSize];
This allocates an array of pointers, but not the actual hashtablenodes. In the following loop you try to write to them which is undefined behaviour.
You are missing in your loop:
h->hashTableNodeArray[i] = new HashTableNode;
The problem is here:
h->hashTableNodeArray = new HashTableNode *[h->tSize];
for(int i = 0; i < h->tSize; ++i){
// this is where it is showing runtime error
h->hashTableNodeArray[i]->bCount = 0;
h->hashTableNodeArray[i]->next = nullptr;
}
You allocate an array of pointers, but don't actually make the pointers point anywhere valid which means their values are indeterminate (and in reality seemingly random). You then proceed to dereference these uninitialized pointers, and write to memory using the pointers, without knowing where in memory you will write.
This leads to undefined behavior, and most likely your crash.
The solution? Either don't use pointers, or explicitly allocate the memory for the pointers. My recommendation is to stop using pointers altogether, create proper copy- and move-constructors, and use std::vector instead.

I am getting a pointer being free but not allocated error when running make, make test in putty

I am very new to object oriented programming, pointer use and allocating memory in C++. I am working on an assignment for class and initially I had it pass the first three tests listed below by having an array, grade_array, that in the addScore function looked like grade_array[count -1] = grade. Then it would be used in the mean function.
I know this is not the correct way to go about this because I was getting seg faults, so I know I need to have an array, then create a new array (twice the size) that allocates more memory so that I can put the values of the first one into the new one, and then delete to not get memory leaks. The real problem I am having is I do not know if I am even close to correct on the way I am doing this. The error I am getting:
Running cxxtest tests (5 tests)testrunner(85436) malloc: *** error for object 0x107a87970: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
make: *** [test] Abort trap: 6
I have seen a lot of people having similar problems and posting about them on this very site I just cannot seem to fix mine. I saw that it could be that I made a new pointer and tried to them have them point to the same thing so when one deletes the other has nothing to delete or that my initializer is wrong as it doesn't do much. Like I said, very new to the topic so sorry if I have a million questions and so many errors. I have spent a lot of time on this already and was hoping I could maybe get some advice before I waste more time, thanks in advance!
Gradebook.h
#ifndef GRADEBOOK_H
#define GRADEBOOK_H
#include <string>
using namespace std;
class Gradebook {
public:
Gradebook();
Gradebook(const string& filename);
Gradebook(const Gradebook& that);
virtual ~Gradebook();
void initCount();
void addScore(double grade);
double getScoreAt(int i);
int getCount(int i);
string getSourceFile();
double getMean(); // change back to double
double getMin();
double getMax();
double getMedian();
double getStdDev();
int scoresInRange(double low, double high);
private:
string filename;
int* grade_array;
int new_size;
int count;
int count_tracker;
int* grade_point;
};
#endif
Gradebook.cpp
void Gradebook::initCount(){
count = 0;
}
Gradebook::Gradebook() {
}
Gradebook::Gradebook(const string& filename) : filename(filename) {
//this->filename = filename; // i beleive that filename(filename) does this line
//grade_array = new int[this->getCount(0) +1];
}
Gradebook::Gradebook(const Gradebook& that) {
}
Gradebook::~Gradebook() {
for ( int i = 0; i < this->getCount(0); i ++){
delete &grade_array[i];
}
delete grade_array;
}
void Gradebook::addScore(double grade) {
int count_tracker = this->getCount(1); //number of elements in array currently
// grade_array = new int[count_tracker ];
// grade_array = new int[1]; // grade_array is just a *array
grade_array[count_tracker -1 ] = grade; // array[0] is first not array[1]
new_size = count_tracker * 2;
int* new_array = new int[new_size];
for (int i = 0; i < count_tracker ; i++) {
new_array[i] = grade_array[i];
}
delete[] grade_array;
grade_array = new_array;
count_tracker = new_size;
}
double Gradebook::getScoreAt(int i) {
return grade_array[i];
}
int Gradebook::getCount(int i) {
if (i == 1){
count = count + 1;
}
else{
//don't want to add to the actual count
}
return count;
}
string Gradebook::getSourceFile() {
//ifstream foo;
//foo.open(filename);
return filename;
}
double Gradebook::getMean() {
double mean = 0;
count_tracker = this->getCount(0);
for (int i = 0; i < count_tracker ; i++){
//mean = (*(&(grade_array[i])- (bit_count))) + mean;
mean = grade_array[i] + mean;
}
return (mean/count_tracker);
}
GradebookTest.h
#ifndef GRADEBOOK_TEST_H
#define GRADEBOOK_TEST_H
#include <Gradebook.h>
#include <cxxtest/TestSuite.h>
class GradebookTest : public CxxTest::TestSuite {
public:
void testDefaultConstructor(){
string filename = "data1.txt";
Gradebook a(filename);
TS_ASSERT_EQUALS("data1.txt" , a.getSourceFile());
}
void testAddOne() {
Gradebook gb;
gb.initCount();
gb.addScore(110);
TS_ASSERT_EQUALS(120, gb.getScoreAt(1));
TS_ASSERT_DELTA(110, gb.getMean(), 0.001);
TS_ASSERT_EQUALS(4, gb.getCount(0) );
}
void testAddMultiple() {
Gradebook gb;
gb.addScore(75);
TS_ASSERT_EQUALS(1, gb.getCount(0) );
gb.addScore(85);
TS_ASSERT_EQUALS(2, gb.getCount(0));
TS_ASSERT_DELTA(85, gb.getMean(), 0.001);
}
#endif
I think the following is wrong
for ( int i = 0; i < this->getCount(0); i ++){
delete &grade_array[i];
}
You don't need this for loop since you only allocate memory for grad_array. One delete grade_array; is enough.