Seg fault is eliminated when copying char** -- why is this? - c++

class uid
{
public:
char id[6] = {'0','0','0','0','0','0'};
uid() {}
~uid() {}
inline void recursive(int x)
{
if(':' == id[x])
{
id[x] = '0';
++id[--x];
recursive(x);
}
}
char* operator++()
{
++id[5];
recursive(5);
return id;
}
void write(char* pchar) const
{
for(int i = 0; i < 6; ++i)
pchar[i] = id[i];
}
};
using namespace std;
int main(int argc, char** argv)
{
const int MAX = 5000000;
uid c;
char** arr = new char*[MAX];
//char** it = arr;
//loop 1
for(int i = 0; i < MAX; ++i)
arr[i] = new char[6];
cout << "allocated" << endl;
//loop 2
for(int i = 0; i < MAX; ++i)
{
++c;
c.write(arr[i]);
}
cout << "data written" << endl;
for(int i = 0; i < MAX; ++i)
delete[] arr[i];
cout << "deleting arr" << endl;
delete[] arr;
return 0;
}
Running this will cause a seg fault in loop 2 when i == 999999 -- However, when adding the line:
char** it = arr;
The seg fault disappears -- does anyone have any ideas of why this happens?
Thanks

As soon as you go past 999,999 you are writing to memory not owned by c. Declaring it changes the memory map enough that there is no immediate segfault, but the code is still not correct, and any other small change might bring back the fault.

Here's how to fix it:
inline void recursive(int x)
{
if(':' == id[x])
{
id[x] = '0';
if (x) { // <-- added this
++id[--x];
recursive(x);
}
}
}
Now overflow will wrap around to 000000 instead of creating a 7 digit number in a space not big enough to hold it.

Related

error in the window getting the number -172492288 at the end of the while loop

#include<iostream>
#include<fstream>
using namespace std;
int *elementShifter(int[], int);
int main()
{
int SIZE = 50;
int array[SIZE];
ifstream infile("Gradelist.txt");
if (!infile)
{
cout << "File not found" << endl;
return -1;
}
int count = -1,data=0;
while (!infile.eof())
{
count++;
if (count < 0 || count > 50)
return -1;
else
{
infile >> array[count];
}
cout << array[count] << endl;
}
cout << endl;
int *s=elementShifter(array, count);
for (int i = 0; i <=count; i++)
{
cout << *s << endl;
s++;
}
return 1;
}
int *elementShifter(int arr[], int size)
{
int *newArr = new int[size + 1];
newArr[0] = 0;
for (int i = 0; i < size; i++)
{
newArr[i+1]=arr[i];
}
return newArr;
}
I just cannot figure out why i am getting this number here
This is reworked into slightly more idiomatic C++, but there's stuff here that might not fly in whatever course you're in, so adapt accordingly:
#include<iostream>
#include<fstream>
// using namespace std; is a bad habit to get into, that prefix
// exists for an important reason: Code separation
// Tip: If you define before you reference a function in your code,
// there is no need for a separate declaration.
// Note use of const on arguments that are not mutated
void unshift(int*& array, size_t& size, const int elem) {
int *resized = new int[++size];
// Insert at the start of the array
resized[0] = elem;
// Copy the remainder
for (int i = 1; i < size; ++i) {
resized[i] = array[i-1];
}
// Don't forget to release the old memory or you have a leak
delete[] array;
// Since the pointer is passed in as a reference, easy to swap it
array = resized;
}
int main() {
size_t size = 1; // size_t is often used for "size"-type args
int *array = new int[size];
std::ifstream infile("Gradelist.txt");
if (!infile) {
// Use std::cerr for errors.
std::cerr << "File not found" << std::endl;
return -1;
}
// infile evaluates as true so long as it has data to read.
while (infile) {
// You already have a count, it's "size"
if (size> 50) {
return -1;
}
int input;
infile >> input;
// This function takes mutable arguments, so they change via
// references.
unshift(array, size, input);
}
std::cout << std::endl;
for (int i = 0; i < size; ++i) {
std::cout << array[i] << std::endl;
}
// Take out the trash
delete[] array;
// Return zero on success, non-zero on failure.
return 0;
}
Of course a lot of this code goes away if you can use std::vector<int> and push_back(), but if you need to learn how to do this at a low-level, here you are with pointers and all the mess they create.
The goal in modern C++ is to avoid using pointers and instead lean heavily on the Standard Library to help you out.

Solving Segmentation Fault(core dumping) error

This program doubles the every second integer for the account number given and if the number is greater than 10 it is subtracted by 9. Then output whether the number entered is correct or not. Assuming that the account number is off 5 numbers. I wrote this program but does not get the answer for few number but got a correct answer for other number. Thanks for hint.
#include <iostream>
class AccountNumber {
private:
int size = 5;
int *p;
public:
AccountNumber() { int *p = new (std::nothrow) int[size]; }
~AccountNumber() { delete[] p; }
void getaccount() {
int acc;
std::cout << "Enter the account number: ";
std::cin >> acc;
for (int i = 0; i < size; i++) {
p[i] = acc % 10;
}
setaccount(p);
}
void setaccount(int a[]) {
for (int i = 0; i < size; i++) {
p[i] = a[i];
}
}
void doubles() {
AccountNumber at;
at.p = new int[size];
at.p = p;
for (int i = 0; i < size; i++) {
if (i % 2 == 1) {
at.p[i] = at.p[i] * 2;
if (at.p[i] > 10) {
at.p[i] = at.p[i] - 9;
}
}
}
p = at.p;
}
bool sum() {
bool ot;
int sum = 0;
for (int i = 0; i < size; i++) {
sum = sum + p[i];
}
int mod = sum % 10;
if (mod == 0) {
ot = true;
} else {
ot = false;
}
return ot;
}
void display(std::ostream &outs) {
bool ot = sum();
doubles();
outs << "Account number entered is ";
if (ot) {
outs << " correct.\n";
} else {
outs << " is not correct. \n";
}
}
};
int main(int argc, char const *argv[]) {
AccountNumber accn;
accn.getaccount();
accn.display(std::cout);
return 0;
}
Output
Enter the account number: 35556
Segmentation fault (core dumped)
I don't know where I'm going wrong.
The issue here is that you never allocate p. Look at your constructor:
AccountNumber()
{
int *p = new(std::nothrow) int[size];
}
Here you are defining a new pointer variable p, which will be used instead of the member pointer variable p you defined in the private fields. What happens here is that you are allocating an int array for a new variable p, but that variable p gets thrown out at the end of the constructor (and also causes a memory leak because of the dynamic allocation that will never be reclaimed).
What you should do here instead is simply assigning the new allocated array to the member pointer variable p without redefining it, ie.
AccountNumber() {
p = new (std::nothrow) int[size];
}
And to prevent such mistakes from happening again, you should consider using a specific naming convention for class members, such as m_ prefix (for example)
class AccountNumber {
private:
int m_size = 5;
int *m_p;
public:
AccountNumber() {
m_p = new (std::nothrow) int[size];
}
};

run failed error while using qsort in c++

I wrote the following code for counting the frequency of names and then printing out the names in lexicographic order with their frequencies.The input here is supposed to be n number of names.So for sorting i wrote qsort function but i guess there is some error in it which i am not able to find bcoz using using other sorting method besides qsort works fine for this code.Please suggest what is the error as i have tried but found no help.below is the code snippet
#include <cstdlib>
#include<stdio.h>
#include<string.h>
struct stu
{
char name[100];
int no;
};
int cmpfunc(const void* p,const void *q){
struct stu *a = *((struct stu**)p);
struct stu *b = *((struct stu**)q);
int str=strcmp(a->name,b->name);
if(str>0) return 1;
if(str<0) return -1;
else return 0;
}
int main(int argc, char** argv) {
int n,k=0;
scanf("%d",&n);
struct stu* data[1000];
for(int i=0 ; i<n ; i++)
{
char nam[100];
scanf("%s",nam);
if(i==0)
{
struct stu* temp=(struct stu*)(malloc(sizeof(struct stu)));
strcpy(temp->name,nam);
temp->no=1;
data[k++]=temp;
}
else
{
int j;
for(j=0 ; j<k ; j++)
{
if(strcmp(data[j]->name,nam)==0)
{
data[j]->no++;
break;
}
}
if(j==k)
{
struct stu* temp=(struct stu*)(malloc(sizeof(struct stu)));
strcpy(temp->name,nam);
temp->no=1;
data[k++]=temp;
}
}
}
qsort(data, k, sizeof(struct stu*),cmpfunc);
for(int i=0 ; i<k ; i++)
{
printf("%s %d\n",data[i]->name,data[i]->no);
}
return 0;
}
if i give input as
5
abcd
abcd
fgh
fgr
fgh
the output is run failed
With the exception of <cstdio>, your code looks much more like C than C++. Perhaps you meant to use <stdio.h>, heed various warnings against casting malloc, check return values and use a C compiler, but this question is tagged C++. In C++ there are far more sensible idioms, for example:
std::string instead of char* / char[].
std::cin/std::cout instead of scanf/printf.
std::vector instead of struct stu* data[1000].
size_t instead of int for array indexes and looping over arrays.
new/delete/unique_ptr instead of malloc/free.
using namespace std;
struct stu {
string name;
int no;
stu() {
}
};
int cmpfunc(const stu *p, const stu *q) {
return p->name < q->name;
}
int main(int argc, char** argv) {
size_t n;
cin >> n;
vector<stu*> data;
for (size_t i = 0; i < n; i++)
{
string nam;
cin >> nam;
if (i == 0)
{
auto* temp = new stu();
temp->name = nam;
temp->no = 1;
data.push_back(temp);
}
else
{
int j;
for (j = 0; j < data.size(); j++)
{
if(data[j]->name == nam)
{
data[j]->no++;
break;
}
}
if (j == data.size())
{
auto* temp= new stu();
temp->name = nam;
temp->no = 1;
data.push_back(temp);
}
}
}
std::sort(data.begin(), data.end(), cmpfunc);
for (int i = 0; i < data.size(); i++)
{
cout << data[i]->name << data[i]->no << endl;
delete data[i];
}
return 0;
}

Implementation of Lamport's Bakery Algorithm has seg faults with more than 1 thread

I'm implementing Lamport's Bakery Algorithm using pthreads and a Processor class to act as shared memory. With a single thread it works fine, with 2 threads I get the seg fault after thread 2 runs through all 30 attempts to access the 'bakery':
dl-tls.c: No such file or directory.
With 3 or more threads I get the seg fault after outputting "here" twice from the bakeryAlgo function:
0x0804ae52 in Processor::getNumber (this=0x5b18c483) at Processor.cpp:33
bakery.cpp
struct argStruct {
vector<Processor>* processors;
Processor* processor;
};
int findMax(vector<Processor>* processors) {
int max = -99;
for (int i = 0; i < processors->size(); i++) {
if (processors->at(i).getNumber() > max) {
max = processors->at(i).getNumber();
}
}
return max;
}
void* bakeryAlgo(void* arg) {
struct argStruct* args = static_cast<struct argStruct *>(arg);
cout << "here" << endl;
for (int i = 0; i < 30; i++) {
args->processor->setChoosing(1);
args->processor->setNumber(findMax(args->processors));
args->processor->setChoosing(0);
for (int j = 0; j < args->processors->size(); j++) {
int jChoosing = args->processors->at(j).getChoosing();
int jNumber = args->processors->at(j).getNumber();
int jId = args->processors->at(j).getId();
int pNumber = args->processor->getNumber();
int pId = args->processor->getId();
if (jId != pId) {
while (jChoosing != 0) {}
while (jNumber != 0 && ((jNumber < pNumber) || ((jNumber == pNumber) && (jId < pId)))) { }
}
}
cout << "Processor: " << args->processor->getId() << " executing critical section!" << endl;
args->processor->setNumber(0);
}
}
int main(int argc, char *argv[]) {
// Check that a command line argument was provided
if (2 == argc) {
int numProcessors = atoi(argv[1]);
vector<Processor> processors;
vector<argStruct> argVect;
vector < pthread_t > threads;
for (int i = 0; i < numProcessors; i++) {
Processor p = Processor(i);
processors.push_back(p);
}
for (int i = 0; i < numProcessors; i++) {
pthread_t processorThread;
struct argStruct args;
args.processors = &processors;
args.processor = &processors.at(i);
argVect.push_back(args);
threads.push_back(processorThread);
pthread_create(&threads.at(i), NULL, &bakeryAlgo, &argVect.at(i));
}
for (int i = 0; i < numProcessors; i++) {
pthread_join(threads.at(i), NULL);
}
}
else {
cout << "Usage: bakery num, num is number of threads." << endl;
}
return 0;
}
The code in Processor.cpp / Processor.h is simple, it's just a few getters and setters on the values id, choosing, and number, with a default constructor and a constructor that takes an int id.
Processor::Processor() {
}
Processor::Processor(int idval) {
id = idval;
choosing = 0;
number = 0;
}
Processor::~Processor() {
}
int Processor::getChoosing() {
return choosing;
}
int Processor::getNumber() {
return number;
}
int Processor::getId() {
return id;
}
void Processor::setChoosing(int c) {
choosing = c;
}
void Processor::setNumber(int n) {
number = n;
}
Does anyone have any idea why these seg faults are occuring? The places gdb says they are occuring look like innocent lines of code to me.
Are you using a pointer to a vector defined in main as your data? Stack is not shared among threads, so the other threads accessing this memory would be undefined behavior at best. I expect this is the source of your troubles.
You are taking the address of an element in a vector which is changing:
for (int i = 0; i < numProcessors; i++) {
pthread_t processorThread;
struct argStruct args;
args.processors = &processors;
args.processor = &processors.at(i);
argVect.push_back(args);
threads.push_back(processorThread);
// danger!
pthread_create(&threads.at(i), NULL, &bakeryAlgo, &argVect.at(i));
}
Each time a new thread is pushed onto the threads vector, the vector may be relocated in memory, so the pointer that you passed to pthread_create may be pointing to garbage when the next thread is added.
You want to do this instead:
for (int i = 0; i < numProcessors; i++) {
pthread_t processorThread;
struct argStruct args;
args.processors = &processors;
args.processor = &processors.at(i);
argVect.push_back(args);
threads.push_back(processorThread);
}
for (int i = 0; i < numProcessors; i++) {
pthread_create(&threads.at(i), NULL, &bakeryAlgo, &argVect.at(i));
}
By waiting until all the elements are added to the vector before you create your threads, you are now passing pointers that stay good while the threads are running.

C++ HEAP error when delete [] is called

I keep getting the error in VS 2100 "CRT detected that the application wrote to memory before start of heap buffer"
Can anyone help? My int Main is all the way on the bottom. The error occur when the delete [] command is run on the operator= function
#include "intset.h"
const int MAXINITIALSIZE = 5;
int IntSet::numOfArray = 0;
IntSet::IntSet(int a, int b, int c, int d, int e)
{
numOfArray++;
int tempArray[] = {a, b, c, d, e};
size = determineHighest(tempArray) + 1; //determines largest int
cout << "size is " << size << endl;
arrayPtr = new bool[size]; //creates array of bool
for (int i = 0; i < size; i++) //fill bool array
{
arrayPtr[i]= false; //arrayptr is a bool pointer created in the header
}
for (int i = 0; i < MAXINITIALSIZE; i++)
{
arrayPtr[tempArray[i]]= true;
}
for (int i = 0; i < size; i++)
{
cout << &arrayPtr[i] << endl;
}
}
IntSet::IntSet(const IntSet &intsetObject)
{
numOfArray++;
size = intsetObject.size;
arrayPtr = new bool[size];
for (int i = 0; i < size; i++)
{
if (intsetObject.arrayPtr[i])
arrayPtr[i] = intsetObject.arrayPtr[i];
}
}
IntSet::~IntSet()
{
--numOfArray;
delete [] arrayPtr;
arrayPtr = NULL;
}
int IntSet::determineHighest(int tempArray[])
{
int temp = tempArray[0];
for (int i = 1; i < MAXINITIALSIZE; i++)
{
if (tempArray[i] > temp)
temp = tempArray[i];
else
continue;
}
return temp;
}
IntSet& IntSet::operator=(const IntSet &intsetObject) //ask about IntSet&
{
cout << "inside operator=" << endl;
if (&intsetObject != this)
{
for (int i = 0; i < size; i++)
{
cout << &arrayPtr[i] << endl;
}
delete [] arrayPtr; //HEAP ERROR HERE!
for (int i = 0; i < size; i++)
{
cout << &arrayPtr[i] << endl;
}
size = intsetObject.size
arrayPtr = new bool[size]();
for (int i = 0; i < size; i++)
{
if (intsetObject.arrayPtr[i])
arrayPtr[i] = intsetObject.arrayPtr[i];
}
}
return *this;
}
ostream& operator<<(ostream &output, const IntSet &intsetObject)
{
output << "{ ";
for (int i = 0; i < intsetObject.size; i++)
{
if (intsetObject.arrayPtr[i] == true)
{
output << i << " ";
}
else
continue;
}
output << "}";
return output;
}
//main
#include "intset.h"
int main() {
IntSet object2(9);
IntSet object4(3,6);
object4 = object2;
return 0;
}
This can only happen if arrayPtr is accessed with a negative index. I suspect your defaults for a,b,c,d,e are -1 in the declaration for IntSet::IntSet, so it is writing to arrayPtr[-1] in the set-true loop. Check for tempArray[i] >= 0 there.
Also, you can't print the array after you have deleted it, so you should remove those lines after the delete, although they should be "harmless" in that only garbage will be printed, but who knows - the OS could release the page containing the array and it could segfault your program.
Finally, you should not test if (intsetObject.arrayPtr[i]) in the copy & = operators. Otherwise all "false" elements in the source array become uninitialized in the destination array (new bool[size] does not initialize the array to all false).