Segmentation fault when calling a class constructor - c++

I'm trying to instantiate a class for a specific implementation of a symbol table and, following the instructions for the project, I'm doing it via a pointer. My constructor does a lot as it is the thing building the symbol table from a text file, but I'm getting a Segmentation fault error at the end of the constructor. What I don't understand is what exactly is giving me this error. I've done a bit of debugging and it seems my constructor is running just fine, as it gets to the breakpoint I put at the very last bracket and all the data is in the vector as I expected. When it tries to step out of the constructor and back to the main file, though, it gives me that error.
The main file is as follows:
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string.h>
#include <time.h>
using namespace std;
#include "tabeladesimbolos.hpp"
typedef char * String;
typedef int * Integer;
int main(int argc, char *argv[])
{
fstream arqTexto;
/* abra arquivo com texto */
arqTexto.open(argv[1]);
if (arqTexto.fail())
{
cout << "ERRO: arquivo" << argv[1] << "nao pode ser aberto.\n";
exit(EXIT_FAILURE);
}
arqTexto.close();
string nome_arquivo = argv[1];
/* crie a ST*/
cout << "criando ST...\n";
/* usadas para medir tempo de processamento */
clock_t start, end;
double elapsed = 0;
start = clock();
vetorDes *st = new vetorDes(nome_arquivo);
end = clock();
/* calcule o tempo */
elapsed = ((double)(end - start)) / CLOCKS_PER_SEC;
cout << "arquivo lido e ST construida em " << elapsed << " segundos\n";
delete st;
return 0;
}
The error happens in the following line:
vetorDes *st = new vetorDes(nome_arquivo);
The file with the constructor (tabeladesimbolos.hpp) is:
#include <string>
#include <string.h>
#include <iostream>
#include <fstream>
#include <vector>
typedef char * String;
typedef int * Integer;
using namespace std;
struct Valor
{
String chave;
Integer valor;
};
class vetorDes
{
vector<Valor> vetor;
public:
vetorDes(string nomeArquivo);
void insere(String chave, Integer valor);
Integer devolve(String chave);
};
vetorDes::vetorDes(string nomeArquivo)
{
ifstream arqTexto;
String palavra;
Integer aux = nullptr;
vetor.reserve(10000);
arqTexto.open(nomeArquivo);
while (arqTexto >> palavra)
{
aux = devolve(palavra);
if (aux == nullptr)
{
int* um = new int;
*um = 1;
insere(palavra, um);
}
else
{
(*aux)++;
}
}
}
void vetorDes::insere(String chave, Integer valor)
{
Valor *aux = new Valor;
aux->chave = (String) malloc(20*sizeof(char));
strcpy(aux->chave, chave);
aux->valor = valor;
int maxsize = vetor.max_size();
int currentsize = vetor.size();
vetor.push_back(*aux);
return;
}
Integer vetorDes::devolve(String chave)
{
for (std::size_t i = 0; i < vetor.size(); ++i)
{
String teste = vetor[i].chave;
if (!strcasecmp(teste, chave))
{
return vetor[i].valor;
}
}
return nullptr;
}
My debugger gets me to that last } in the constructor without error, which leads me to believe the problem is with the way I allocate something as it only comes up when the program tries to finish the "new vetorDes" call.
The full error message is:
Program received signal SIGSEGV, Segmentation fault.
__GI___libc_free (mem=0x3b002e6f746e6174) at malloc.c:3103
What am I doing wrong? What am I missing?

String palavra;
...
while (arqTexto >> palavra)
I didn't see anything between declaring palavra, which is a pointer, and reading into it, that made palavara point anywhere. The pointer is uninitialized, so it points to some random place, and you are reading your data into that random place. Anything can happen then, except anything good.

__GI___libc_free (mem=0x3b002e6f746e6174)
The 0x3b002e6f746e6174 is obviously invalid pointer:
it's not in canonical form,
its tail looks like ASCII string tanto.
It is safe to assume that you have some kind of heap overflow (or other heap corruption). Use Valgrind or Address Sanitizer to find the bug.
As N.M. noted, you are doing yourself a great disservice by hiding pointers behind these typedefs:
typedef char * String;
typedef int * Integer;
The bug would be much more noticeable if you didn't:
char *palavra; // uninitialized pointer
...
while (arqTexto >> palavra) // BUG: writes to random memory

Related

C++ Dynamic Array: A value of type "void" cannot be used to initialize an entity of type "int"

I am working on a C++ project for school in which the program will read in a list of numbers from a text file, store them in a dynamic array, then print them out to another text file. To be honest I'm a little lost with the pointers in this, and I am getting the error "A value of type "void" cannot be used to initialize an entity of type "int"" in my main source file.
Main.cpp (this is where I'm getting the error):
#include "dynamic.h"
int main
{
readDynamicData("input.txt","output.txt");
}
dynamic.cpp (the skeleton for the program):
#include "dynamic.h"
void readDynamicData(string input, string output)
{
DynamicArray da; //struct in the header file
da.count = 0;
da.size = 5; //initial array size of 5
int *temp = da.theArray;
da.theArray = new int[da.size];
ifstream in(input);
ofstream out(output);
in >> da.number; //prime read
while (!in.fail())
{
if (da.count < da.size)
{
da.theArray[da.count] = da.number;
da.count++;
in >> da.number; //reprime
}
else grow; //if there are more numbers than the array size, grow the array
}
out << "Size: " << da.size << endl;
out << "Count: " << da.count << endl;
out << "Data:" << endl;
for (int i = 0; i < da.size; i++)
out << da.theArray[i];
in.close();
out.close();
delete[] temp;
}
void grow(DynamicArray &da) //this portion was given to us
{
int *temp = da.theArray;
da.theArray = new int[da.size * 2];
for (int i = 0; i<da.size; i++)
da.theArray[i] = temp[i];
delete[] temp;
da.size = da.size * 2;
}
and dynamic.h, the header file:
#include <iostream>
#include <string>
#include <fstream>
#ifndef _DynamicArray_
#define _DynamicArray_
using namespace std;
void readDynamicData(string input, string output);
struct DynamicArray
{
int *theArray;
int count;
int size;
int number;
};
void grow(DynamicArray &da);
#endif
you have to add parenthesis to main or any function:
int main(){/*your code here ...*/};
2- you are using an unitialized objct:
DynamicArray da; //struct in the header file
da.count = 0;
da.size = 5; //initial array size of 5
so int* theArray is a member data and is uninitialized so welcome to a segfault
all the members of da are not initialized so you have to do before using it.
3- also you add parenthesis to grow function:
else grow(/*some parameter here*/); // grow is a function
4- using namespace std; in a header file is a very bad practice.
tip use it inside source
5- why making inclusion of iostream and string.. before the inclusion guard??
correct it to:
#ifndef _DynamicArray_
#define _DynamicArray_
#include <iostream>
#include <string>
#include <fstream>
/*your code here*/
#endif
main is a function so it needs brackets:
int main(){
// your code
return 0; // because it should return intiger
}
And. Your grow is also a function, so if you want to call it you write grow() and it needs DynamicArray as a parameter.
It is impossible to write working programs on C/C++ any programming language not knowing a basic syntax.

I keep returning the same value for variable howMany

I have a file that has been previously filled with data. The file consists of an array of structures. Each structure represents a round and each array position represents up to 20 rounds for an individual. My .h file:
define READTWENTY_H
class readTwenty {
public:
readTwenty();
void nonZeroes(int, int &);
struct a_round {
int score;
double course_rating;
int slope;
char date[15];
char place[40];
char mark[1];
}; //end structure definition
struct a_round all_info[20];
FILE *fptr;
}; //end class
#endif
In the data file some "rounds" have actual data in them and some have previously been filled with zeroes. I want to count the zero rounds. I have a loop in which I can ask for another "person" value to look at. This value is sent to a function in which the number of zero rounds is determined and returned by reference to a variable named "howMany".
// readMember.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include "readTwenty.h"
using namespace std;
int main()
{
int person = 0;
readTwenty personData;
int howMany = 0;
while (person != -999) {
cout << "Which member (keyfield) would you like to see? -999 to stop ";
cin >> person;
if (person == -999)
exit(0);
personData.nonZeroes(person-1, howMany);
cout << "The number of non-zero values for this member is " << howMany << endl;
}//end while
return 0;
}
Once sent to the nonzeroes function as "key" I create an offset into the file and read the 20 rounds for that individual and return by reference the value of count back to the calling routine into variable howMany.
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include "readTwenty.h"
#include <errno.h>
#include <cstdio>
readTwenty::readTwenty() {
const char *configfile;
configfile = "scores.dat";
#ifdef WIN32
errno_t err;
if((err = fopen_s(&fptr,configfile, "rb")) != 0)
#else
if ((fp_config = fopen(configfile, "rb")) == NULL)
#endif
fprintf(stderr, "Cannot open cinfig file %s!\n", configfile);
}//end constructor
void readTwenty::nonZeroes(int key, int &count) {
int zeroes = 0;
int offset = key * ((sizeof(all_info[0]) * 20));
fseek(fptr, offset, SEEK_SET);
for (int i = 0; i < 20; i++){
fread(&all_info[i], sizeof(all_info[0]), 1, fptr);
if (all_info[i].score == 0)
zeroes++;
all_info[i].mark[0] = ' ';
}//end for loop
count = 20 - zeroes;
fclose(fptr);
}//end of function nonZeroes
The problem is that the first value that I give for person comes back with the correct number of non-zero rounds. However, each succeeding iteration of the while loop regardless of the second value I give for person comes back with the same result as the first person? Would greatly appreciate any ideas you may have.
I currently have no computer to verify, but one line jumps out to me as it is a common error (for me at least):
The first param to your fread is &all_info[i]; you probably want &(all_info[i]), but this is not how the compiler understands it - & is stronger than [i], so you get (&all_info)[i].
You could also use all_info+i for the same effect.

Deleting a pointer reference crashes the program

I'm learning cpp by myself (I hope I didn't scare you off already), I understand what a pointer or a reference is and I think I get what a reference to a pointer is.
I've written a code that crashes at delete[] ranking; :
open(file) is just a simple function to open a txt file that contains a string and 3 integers each line which goes into zuzel structure:
void read_file(std::ifstream & file, zuzel *& ranking)
{
if(!open(file))
return; //exit function if reading a file failed
int size = 1;
while(!file.eof())
{
zuzel * update = new zuzel[size];
if(ranking != NULL) memcpy(update, ranking, (size-1)*sizeof(*ranking)); //copy existing contents
file >> update[size - 1].nazwa >> update[size - 1].zawodnicy >> update[size - 1].mecze >> update[size - 1].punkty;// add a new team
delete[] ranking; //delete old data
std::cout << "tst"; //just to see if it crashes
ranking = update;
size++;
}
}
int main()
{
zuzel * rank;
std::ifstream file;
read_file(file, rank);
return 0;
}
I found out that you shouldn't delete something that you didn't new, but for example that code doesn't crash :
void funk(int *& a)
{
delete[] a;
}
int main()
{
int a[3] = {3, 4, 6};
int * p = a;
funk(p);
return 0;
}
How can I fix that crash? I'd be much obliged for some simple explanation why does it behave that way.
It will be enough to write
zuzel * rank = 0;
As for the second code snippet then it has undefined behaviour.
zuzel * rank;
//somewhere in read_file:
delete[] ranking; //ranking is a reference to pointer;
//in your case it's referernce to uninitialized pointer rank
Because rank is not initialized, it points to a unknown portion of memory, and your code simply tryes to delete[] the portion anyway...
You need to do set a pointer to address 0 by using one of these:
zuzel * rank=nullptr; //in C++11
zuzel * rank=NULL; //before C++11
zuzel * rank=0; //also legal, but I not recommend this
0 is the special value for any pointer, meaning that it points to nothing.
When you pass pointer set to 0 to delete[] or delete they simply do nothing.
Since you're learning. Please accept this example of how you might prefer to do it. You will find that it's exception-safe and avoids using pointers (and therefore avoids the need for memory management)
main.cpp:
#include <iostream>
#include <vector>
#include <fstream>
#include <string>
#include <algorithm>
#include <iterator>
struct zuzel
{
std::string nazwa, zawodnicy, mecze, punky;
};
std::ostream& operator<<(std::ostream& os, const zuzel& z)
{
return os << z.nazwa << ", "
<< z.zawodnicy << ", "
<< z.mecze << ", "
<< z.punky;
}
std::vector<zuzel> read_zuzels(std::string filename)
{
std::vector<zuzel> results;
std::ifstream f(filename.c_str());
f.exceptions(std::ios::badbit);
while(!f.eof())
{
// add a new team
zuzel new_zuzel;
f >> new_zuzel.nazwa
>> new_zuzel.zawodnicy
>> new_zuzel.mecze
>> new_zuzel.punky;
results.push_back(new_zuzel);
}
return results;
}
using namespace std;
int main()
{
vector<zuzel> zuzels = read_zuzels("input.txt");
copy(zuzels.begin(), zuzels.end(), ostream_iterator<zuzel>(cout, "\n"));
return 0;
}
input.txt:
foo1 bar1 baz1 bazzer1
foo2 bar2 baz2 bazzer2
output:
Compiling the source code....
$g++ main.cpp -o demo -lm -pthread -lgmpxx -lgmp -lreadline 2>&1
Executing the program....
$demo
foo1, bar1, baz1, bazzer1
foo2, bar2, baz2, bazzer2

Segfault with std::list usage

I'm Java user coming over to C++, and I am having a hard time understanding what is going wrong with this statement. My program has been segfaulting anywhere I put the push_back command. So I'm wondering what exactly is going on.
class Process {
public:
int nice;
int arrivalTime;
int cpuBursts;
list<int> burstList;
Process() {
burstList.push_back(10); // Segfaults here...
}
};
Here is the full code:
#include<iostream>
#include<stdlib.h>
#include<fstream>
#include<list>
#include<string.h>
using namespace std;
int calcTimeslice(int priority);
int calcOriginalPrio(int nice);
int readFile(int ,char **);
int calcPrioBonus(int,int);
void tokenizeAndAdd(char *);
class Bursts {
public:
int isCPUBurst;
int time;
Bursts() {}
// Constructor to make it easier to add to list
Bursts(int tempIsCPU, int tempTime) {
isCPUBurst = tempIsCPU;
time = tempTime;
}
};
class Process {
public:
int nice;
int arrivalTime;
int cpuBursts;
list<int> burstList;
Process() {
burstList.push_back(10);
}
};
int main(int arg, char **argv) {
// This is if the file was not correctly read into the program
// or it doesnt exist ...
if(readFile(arg,argv)==-1) {
cout << "File could not be read. \n";
return -1;
}
//cout << "Original Calc Whatever: " << calcOriginal(19) << '\n';
return 0;
}
/*
* Calculates the timeslice based on the priority
*/
int calcTimeslice(int priority) {
double finalCalc;
// This is the given function in the prompt
finalCalc = ( (1 - (priority / 140)) * 290 + (.5) ) + 10;
// Cast to int, this will be a truncate
return ((int)finalCalc);
}
int readFile(int arg, char **argv) {
char *temp,*pointer;
int endOfFile = 1;
// While its not the end of the file
while(endOfFile) {
// Read in the input from stdin
fgets(temp,256,stdin);
// Check to see if this line had a * in it
if(*temp =='*')
endOfFile = 0;
else
tokenizeAndAdd(temp);
}
return 0;
}
void tokenizeAndAdd(char *string) {
char *token = strtok(string," \n");
int i = 0;
Process p;
while(token != NULL) {
cout << token << endl;
if(i>2) { // If it is odd (CPU burst)
if(i%2 == 1) {
int tempInt = atoi(token);
//p.burstList.push_back(tempInt);
}
else { // If it is even (IO burst)
int tempInt = atoi(token);
//p.burstLis.push_back(tempInt);
}
}
else if(i==0)
p.nice = atoi(token);
else if(i==1)
p.arrivalTime = atoi(token);
else if(i==2)
p.cpuBursts = atoi(token);
token = strtok(NULL," \n");
i++;
}
//cout << p.nice << " " << p.arrivalTime << " " << p.cpuBursts << "\n";
//i = 0;
//cout << p.burstList.size() << "\n";
// cout <<
//}
return;
}
/*
* Calculates and returns the original priority based on the nice number
* provided in the file.
*/
int calcOriginalPrio(int nice) {
double finalCalc;
// This is the given function from the prompt
finalCalc = (( nice + 20 ) / 39 ) * 30 + 105.5;
// Cast to int, this is a truncate in C++
return ((int)finalCalc);
}
/*
* Calculates the bonus time given to a process
*/
int calcPrioBonus(int totalCPU, int totalIO) {
double finalCalc;
// How to calculate bonus off of the prompt
if(totalCPU < totalIO)
finalCalc = ( (1 - (totalCPU / (double)totalIO)) * (-5)) - .5;
else
finalCalc = ( (1 - (totalIO / (double)totalCPU)) * 5) + .5;
// Cast to int
return ((int)finalCalc);
}
You are using temp uninitialized in the following code:
char *temp;
...
while(endOfFile) {
fgets(temp,256,stdin);
...
This can have any side effect, since it most likely destroys your stack or parts of the heap memory. It could fail immediately (when calling the fgets() function), it could fail later (as in your sample) or it could even run fine - maybe until you upgrade your OS, your compiler or anything else, or until you want to run the same executable on another machine. This is called undefined behaviour.
You need to allocate space for the temp variable, not a pointer only. Use something like
char temp[256];
...
while(endOfFile) {
fgets(temp,256,stdin);
...
For more information, see the fgets() documentation. The first parameter is a pointer to a char array - that is where fgets() will store the bytes which have been read. In your code, you pass an uninitialized pointer which means that fgets() will store the bytes to an undefined memory location - this is catched by the OS which terminates your application with a segmentation fault.
BTW: You should consider enabling pedantic warnings when compiling - I compiled with
g++ -Wall -pedantic -o list list.cpp
which gave me the following warning:
list.cpp: In function 'int readFile(int, char**)':
list.cpp:76:26: warning: 'temp' may be used uninitialized in this function [-Wuninitialized]
This is probably not the actual code with the error you report. But here is one of the problems with give you UB.
char *temp,*pointer; // uninicialized pointer char temp[1000]; could work?
int endOfFile = 1;
// While its not the end of the file
while(endOfFile) {
// Read in the input from stdin
fgets(temp,256,stdin);
The last function call will read a maximum of 256 bytes from stdin and will write it in the memory pointed by pointer tmp. So, you need to first "prepare" that memory. But with char *tmp; you only define a pointer, with no defined value, that is, with point to some possible unexisting or illegal/inaccessible for you memory. In contrary, char tmp[1000]; will define in the "stack memory" a block of 1000 bytes, with you can point to using simple the variable tmp. Hope this is clear for you.
EDIT:
I don't know why that would change the behavior of the list,
You are right. That is Undefined Behavior (UB). When you write in some unknown memory (pointed by an uninitialized pointer) you may overwrite data or even code that will broke somewhere the correct function of your program in an unpredicted way.
You will need to learn more about pointers but better you use std::string, and look how parse your file using string and stringstream. That will manage for you the memmory,

C++, using stack.h read a string, then display it in reverse

For my current assignment, I have to use the following header file,
#ifndef STACK_H
#define STACK_H
template <class T, int n>
class STACK
{
private:
T a[n];
int counter;
public:
void MakeStack() {
counter = 0;
}
bool FullStack() {
return (counter == n) ? true : false ;
}
bool EmptyStack() {
return (counter == 0) ? true : false ;
}
void PushStack(T x) {
a[counter] = x;
counter++;
}
T PopStack() {
counter--;
return a[counter];
}
};
#endif
To write a program that will take a sentence, store it into the "stack", and then display it in reverse, and I have to allow the user to repeat this process as much as they want. The thing is, I am NOT allowed to use arrays (otherwise I wouldn't need help with this), and am finding myself stumped.
To give an idea of what I am attempting, here is my code as of posting, which obviously does not work fully but is simply meant to give an idea of the assignment.
#include <iostream>
#include <cstring>
#include <ctime>
#include "STACK.h"
using namespace std;
int main(void)
{
auto time_t a;
auto STACK<char, 256> s;
auto string curStr;
auto int i;
// Displays the current time and date
time(&a);
cout << "Today is " << ctime(&a) << endl;
s.MakeStack();
cin >> curStr;
i = 0;
do
{
s.PushStack(curStr[i]);
i++;
} while (s.FullStack() == false);
do
{
cout << s.PopStack();
} while (s.EmptyStack() == false);
return 0;
} // end of "main"
UPDATE
This is my code currently
#include <iostream>
#include <string>
#include <ctime>
#include "STACK.h"
using namespace std;
time_t a;
STACK<char, 256> s;
string curStr;
int i;
int n;
// Displays the current time and date
time(&a);
cout << "Today is " << ctime(&a) << endl;
s.MakeStack();
getline(cin, curStr);
i = 0;
n = curStr.size();
do
{
s.PushStack(curStr[i++]);
i++;
}while(i < n);
do
{
cout << s.PopStack();
}while( !(s.EmptyStack()) );
return 0;
You're on the right track, but you shouldn't be looping until the stack is full -- there are no guarantees curStr consists of at least 256 characters. Instead, loop like as follows...
int n = curStr.size();
do {
s.PushStack(curStr[i++]);
} while (i < n);
Now, you should really not write <bool-expr> == false or <bool-expr> == true... instead, merely write !<bool-expr> and <bool-expr>, respectively. You don't need all of your auto storage specifiers on the local variables, either. Your professor should also look into using the constructor rather than using MakeStack.
edit: It appears you had some trouble translating my code. You only need to i++ once per loop -- this increments our position in the string. As you are doing it now, you are actually incrementing the position twice and thus only pushing every other character.
Use a linked list instead of array in stack.
In the linked list, always store the tail pointer of your list's last node. Each node maintains a reference to your prev node.
A <--- B <---- C (tail)
push:
A <--- B <---- C <---- D (tail)
pop:
A <--- B <---- C (tail)
// D is popped out
when the tail == null, you know it is an empty stack