Where / How is null defined? - c++

Null is not declared?
My code:
// Include necessary libraries
#include <cstdlib> // Exits
#include <iostream> // I/O
#include <cstring> // String functions
using namespace std;
int main(int argc, char *argv[])
{
//Declare local Constants and Variables
const char SOKINP[19] = "23456789TtJjQqKkAa"; // Valid Input Characters
char acCards [5]; // Array to hold up to five cards (user input)
bool bErr; // Loop on Error (Calculated)
int i, // Loop variable (Calculated)
iNbrCrd, // Number of Cards 2-5 (user input)
iNAces, // Number of Aces (Calculated)
iTS; // Total Score (Calculated)
...
for (i=0;i<iNbrCrd;i++){
do {
cout << "Enter Card #" << i << " (2-9,t,j,q,k or a) >";
cin >> acCards[i];
cout << endl;
bErr = (strchr(SOKINP, acCards[i]) == null) ? true : false; // *ERROR*
} while (bErr);
}
return EXIT_SUCCESS;
}
[Error] 'null' was not declared in this scope
How do I declare 'null'? I tried including several other libraries.
I'm using Dev C++ v5.4.2
Thanks, ~d

Its not null. It's NULL in all caps. If writing NULL does not work, you can define it yourself by using
#define NULL 0

Use NULL instead of Null.
If you are using it to initialize a pointer and you are using C++11, use nullptr.
Although NULL works for assigning the pointers(even though NULL is not a pointer type but is integer), you may face problems in the below case:
void func(int n);
void func(char *s);
func( NULL ); // guess which function gets called?
Refer to THIS for more details

Related

Segmentation fault when calling a class constructor

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

Uninitialised local variable from class

When I'm trying to access classes public variable (in this case trying to input text row) it shows that it's uninitialized. However, I declared it in class as a public variable.
I know that's some dummy mistake, but can't find it :D
#include <iostream>
#include <conio.h>
using namespace std;
class stringlength {
private:
int lengt;
public:
char * row;
int len()
{
for (int i = 0, lengt = 0; (*(row + i) != '\0'); i++, lengt++) {}
return lengt;
}
};
int main()
{
stringlength test;
cout << "Enter a string:";
cin >> test.row;
cout << "Length is: " << test.len();
_getch();
}
This program is expected to give a length of the inputted row (like strlen function)
Error is:
Error C4700 uninitialized local variable 'test' used
Thanks for help ;)
Declaring the variable does not mean that it's initialized.
Initialize it in a constructor, or just char * row = nullptr; (if 0 is the intended initialization).
Same for all the variables that you have which have no constructors.
Edit: in this specific case you need to initialize to a new pointer char * row = new char[...]

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.

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,

Generating a random within an interval, except some numbers : EXC_BAD_ACCESS

I use xcode 4 on Mac Os X snow leopard.
I am trying to write a function to generate a random number within an interval, except some numbers.
ie:
int num=5;
random(time(NULL),1,100,&num,NULL);
This must generate a number within 1 and 100, except 5.
So I've written this code:
//
// main.cpp
// CPPTest
//
// Created by Ramy Al Zuhouri on 3/7/12.
// Copyright 2012 __MyCompanyName__. All rights reserved.
//
#include <iostream>
#include <exception>
#include <cstdarg>
#include <cstdlib>
#include <ctime>
using namespace std;
class cannotGenerate : public exception
{
virtual const char* what()
{
return "Cannot generate any number, maybe the interval is empty, or the exluding vector is too large\n";
}
};
// Random number generation
// min : min number (included)
// max : max number (included)
// seed : generator seed
// excp1 first argument of int pointers (the last must be NULL)
// the int pointers represent the numbers that must be excluded
// so that if such number is generated, it has to be generated again
int random(unsigned int seed=(unsigned int)time(NULL),int min=0,int max=RAND_MAX, int* excp1=NULL , ...)
{
// variables
int result,*ptr;
va_list vl;
static unsigned int count=0;
// instructions
srand(seed+count++);
va_start(vl,excp1);
do // this do-while has the purpose to keep generating numbers until the number is correct
{ // correct = within the [min,max] interval and not a number of the list of pointers
result=rand()%(max-min+1)+min;
ptr=excp1;
do // this do-while has the purpose to check all the va_list and to read all arguments
{ // passed to the function
if(ptr!=NULL)
{ // here there is the exception (with gdb 6.3.50) :
if(result==*ptr) // Thread 1: Program received signal: "EXC_BAD_ACCESS".
result=min-1;
ptr=va_arg(vl,int*);
}
else
{
break;
}
}while(ptr!=NULL && (result<min || result>min));
}while(result<min || result>max);
va_end(vl);
// result
return result;
}
int main (int argc, const char * argv[])
{
int excp[]={1,2,3,4};
int rand;
for(int i=0;i<100;i++)
{
rand=random((unsigned int)time(NULL),1,100,&excp[0],&excp[1],&excp[2],&excp[3],NULL);
if(rand==1 || rand==2 || rand==3 || rand==4)
{
cerr << "error" << endl;
break;
}
else
{
printf("%d\n",rand);
}
}
return 0;
}
But with gdb I'm getting this exception:
Thread 1: Program received signal: "EXC_BAD_ACCESS".
In that block ptr can't be NULL, so I can't figure out the reason of this exception.
The issue is that you don't reset the variable argument list after the first run through so it ends up pointing to the memory after the NULL input which results in the exception (if you're lucky).
Try replacing the inner loop in random with the following (note placement of va_start and va_end).
do {
result=rand()%(max-min+1)+min;
va_start(vl,excp1); //note
ptr=excp1;
do
{
if(ptr!=NULL)
{
if(result==*ptr)
result=min-1;
ptr=va_arg(vl,int*);
}
else
{
break;
}
} while(ptr!=NULL && (result<min || result>min));
va_end(vl); //note
}while(result<min || result>max);
That's a lot of code. Try this instead:
int z = ((arc4random() % 100)+1);
if (z == 5){
[self tryAgain]
}else {
return z;
}
(replace 100 with your max, and 5 with any number of excluded variables)
This will generate a random number between 0 and 99, then add one to it. If the result is five, loop it to get a different number.
Also, note this line in your code:
}while(ptr!=NULL && (result<min || result>min));
Is that right? less than or greater than the minimum?