How can I get my queue in C++ work? Unhandeled Exception: Access violation reading location - exception

I got a problem by implementing a queue in C++. I looked for similar problems, but didn't find anything usefull.
I'm using Visual Studio 2019.
I seperated my program in a Main.cpp, a Queue.h and Queue.cpp, Patient.h and Patient.cpp.
I tried to convert the concept for this from Java to C++, but I just can't find a solution for my function getInfo().
I get an exception like this:
Unhandled exception at 0x7C0EF3BE (ucrtbased.dll) in Queue.exe: 0xC0000005: Access violation reading location 0xE8884D8D.
Would be nice if anyone could help me with my problem and explain what I did wrong.
I'm just a beginner so don't be too harsh on me pls xD
Main.cpp:
#include "Queue.h"
#include "Patient.h"
int main() {
Queue queue;
Patient patient1("Name1");
Patient patient2("Name2");
queue.add(patient1);
queue.add(patient2);
queue.getInfo();
}
Queue.h:
#pragma once
#include <iostream>
#include "Patient.h"
using namespace std;
class Queue {
private:
Patient* beginning;
Patient* end;
int amount;
public:
Queue();
void add(Patient p);
Patient remove();
void getInfo();
};
Queue.cpp:
#include "Queue.h"
Queue::Queue() {
beginning = 0;
end = 0;
amount = 0;
}
void Queue::add(Patient p) {
if (amount == 0) {
beginning = &p;
end = &p;
} else {
end->setFollower(p);
end = &p;
}
amount++;
}
Patient Queue::remove() {
if (amount == 0) {
cout << "You can't remove a patient. The Queue is empty!" << endl;
} else {
*beginning = beginning->getFollower();
amount--;
}
return *beginning;
}
void Queue::getInfo() {
if (amount == 0) {
cout << "The Queue is empty!" << endl;
} else {
cout << "There are " << amount << " Patients in the Queue!" << endl;
cout << "The following list provides all Patients in the Queue-order:" << endl;
beginning->getInfo();
}
}
Patient.h:
#pragma once
#include <iostream>
#include <string>
using namespace std;
class Patient {
private:
string name;
Patient* follower;
string* nameptr;
public:
Patient(string newname);
void setFollower(Patient p);
Patient getFollower();
void getInfo();
};
Patient.cpp:
#include "Patient.h"
Patient::Patient(string newname) {
name = newname;
follower = 0;
nameptr = &name;
}
void Patient::setFollower(Patient p) {
follower = &p;
}
Patient Patient::getFollower() {
return *follower;
}
void Patient::getInfo() {
cout << *nameptr << endl;
if (follower == 0) {
cout << "No follower existing!" << endl;
}
else {
follower->getInfo();
}
cin.get();
}

There are a few places where you mix up passing by value with passing by reference.
To start with, the first problem is here:
void Queue::add(Patient p) {
if (amount == 0) {
beginning = &p;
end = &p;
} else {
end->setFollower(p);
end = &p;
}
amount++;
}
You are passing the value of Patient p rather than a reference to the actual object. To fix this you only need to add an "&" to your functional call like this:
void Queue::add(Patient& p) {
if (amount == 0) {
beginning = &p;
end = &p;
} else {
end->setFollower(p);
end = &p;
}
amount++;
}
Note the "&" in the parameters list. Then you must also update the function header:
class Queue {
private:
Patient* beginning;
Patient* end;
int amount;
public:
Queue();
void add(Patient& p);
Patient remove();
void getInfo();
};
You must also pass by reference for your setFollower function:
void Patient::setFollower(Patient& p) {
follower = &p;
}
and in the header file:
void setFollower(Patient& p);
What you need to know going forward is that in C++ all arguments are passed by value unless you specify passing by reference in the function's parameter list. Here is an article about passing variables to functions if you'd like to read more (https://iq.opengenus.org/call-by-value-vs-call-by-reference-cpp/).

Related

Dynamic function call through member function via map and arguments unpacking through template

I have tried code written on some link provided for dynamic function call , but unable to run code on machine .I tried to run code present at stackoverflow.com/questions/15764078/dynamically-creating-a-c-function-argument-list-at-runtime through member function.
It is is giving bad call exception while running :
Code snnippets
#include <iostream>
#include <functional>
#include <stdexcept>
#include <string>
#include <boost/any.hpp>
class Test;
class Test
{
public:
template <typename Ret, typename... Args>
Ret callfunc (std::function<Ret(Args...)> func, std::vector<boost::any> anyargs);
template <typename Ret>
Ret callfunc (std::function<Ret()> func, std::vector<boost::any> anyargs)
{
if (anyargs.size() > 0)
throw std::runtime_error("oops, argument list too long");
return func();
}
template <typename Ret, typename Arg0, typename... Args>
Ret callfunc (std::function<Ret(Arg0, Args...)> func, std::vector<boost::any>anyargs){
if (anyargs.size() == 0)
throw std::runtime_error("oops, argument list too short");
Arg0 arg0 = boost::any_cast<Arg0>(anyargs[0]);
anyargs.erase(anyargs.begin());
std::function<Ret(Args... args)> lambda =
([=](Args... args) -> Ret {
return func(arg0, args...);
});
return callfunc (lambda, anyargs);
}
template <typename Ret, typename... Args>
std::function<boost::any(std::vector<boost::any>)> adaptfunc (Ret (Test::*func)(Args...)) {
std::function<Ret(Test*,Args...)> stdfunc = func;
std::function<boost::any(std::vector<boost::any>)> result =
([=](std::vector<boost::any> anyargs) -> boost::any {
return boost::any(callfunc(stdfunc, anyargs));
});
return result;
}
int func1 (int a)
{
std::cout << "func1(" << a << ") = ";
return 33;
}
};
int main ()
{
Test a;
std::vector<std::function<boost::any(std::vector<boost::any>)>> fcs =
{
a.adaptfunc(&Test::func1)};
std::vector<std::vector<boost::any>> args =
{{777}};
// correct calls will succeed
for (int i = 0; i < fcs.size(); ++i)
std::cout << boost::any_cast<int>(fcs[i](args[i])) << std::endl;
return 0;
}
This code compiled successfully
But it failed to run and crashed
In main function for loop.
Function needs typecast according to their signature e.g.:
a.adaptfunc((int(*)(int))&Test::func1)};
After this typecast function call will not fail

private C++ template function in a regular class - OpenCL

I am trying to create a customized class around the OpenCL C++ wrapper to get some specific information from the available devices. For example get the number of available GPUs, CPUs, etc. in a platform. To reduce code I decided to implement a private template function as shown below:
//Devices.hpp
class Devices
{
public:
Devices(const cl::Platform& inputPlatform)
{
inputPlatform.getDevices(CL_DEVICE_TYPE_ALL, &availableDevices);
}
cl_int getTotalNumberOfDevices()
{
return availableDevices.size();
}
cl_int getTotalNumberOfGPUs()
{
return countDevicesWithSpecificProperty(CL_DEVICE_TYPE, CL_DEVICE_TYPE_GPU);
}
private:
std::vector<cl::Device> availableDevices;
template <typename T>
cl_int countDevicesWithSpecificProperty(
const cl_device_info& deviceInfo,
const T& searchPropertyValue)
{
cl_int totalNumberOfDevices = getTotalNumberOfDevices();
T response;
cl_int count = 0;
for (cl_int i = 0; i < totalNumberOfDevices; ++i)
{
try
{
availableDevices.at(i).getInfo(deviceInfo, &response);
}
catch (cl::Error e)
{
return e.err();
}
if (response == searchPropertyValue) ++count;
}
return count;
}
};
While the code compiles correctly, getInfo throws a CL_INVALID_VALUE error. When I implemented the same code using regular function (instead of a template) the code works fine:
//Devices.hpp
class Devices
{
public:
Devices(const cl::Platform& inputPlatform)
{
inputPlatform.getDevices(CL_DEVICE_TYPE_ALL, &availableDevices);
}
cl_int getTotalNumberOfDevices()
{
return availableDevices.size();
}
cl_int getTotalNumberOfGPUs()
{
return countDevicesWithSpecificProperty(CL_DEVICE_TYPE, CL_DEVICE_TYPE_GPU);
}
private:
std::vector<cl::Device> availableDevices;
cl_int countDevicesWithSpecificProperty
(const cl_device_info& deviceInfo,
const cl_device_type& searchPropertyValue)
{
cl_int totalNumberOfDevices = getTotalNumberOfDevices();
cl_device_type response;
cl_int count = 0;
for (cl_int i = 0; i < totalNumberOfDevices; ++i)
{
try
{
availableDevices.at(i).getInfo(deviceInfo, &response);
}
catch (cl::Error e)
{
return e.err();
}
if (response == searchPropertyValue) ++count;
}
return count;
}
};
Any thoughts?
PS: The method is invoked as follows:
//main.cpp
#define __CL_ENABLE_EXCEPTIONS
#include <iostream>
#include <vector>
#include <CL/cl.hpp>
#include "Devices.hpp"
int main()
{
try
{
std::vector<cl::Platform> availablePlatforms;
cl::Platform::get(&availablePlatforms);
Devices d(availablePlatforms[0]);
std::cout << d.getTotalNumberOfGPUs() << std::endl;
}
catch (cl::Error e)
{
std::cout << e.what() << std::endl << e.err() << std::endl;
}
return 0;
}
The issue is that your response variable doesn't have the correct type in your templated version. This is because you are passing CL_DEVICE_TYPE_GPU to the templated parameter, which is a preprocessor macro, and so won't necessarily have the correct type needed for the device info query.
One solution is to explicitly cast the templated parameter to ensure it has the correct type:
return countDevicesWithSpecificProperty(CL_DEVICE_TYPE, (cl_device_type)CL_DEVICE_TYPE_GPU);
Check assembler listing for both cases. There should be some difference in what compiler generates.

C++ Linked List Deep Copy Constructor and Assignment Overloaded

#ifndef LIST
#define LIST
#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;
typedef string ElementType;
class List
{
private:
class Node
{
public:
ElementType data;
Node * next;
Node()
:data(ElementType()), next(NULL)
{}
Node(ElementType initData)
:data(initData), next(NULL)
{}
}; // end of Node class
typedef Node * NodePointer;
public:
private:
NodePointer first;
int mySize;
}; // end of List class
This is my overloaded assignment operator, im not sure what im doing wrong, but im beyond frustrated,I've searched the web and read different forums and cannot find a solution to do this, could someone please push me in the right direction, I left out all my public member functions, because none of them operate on my overloaded assignment and copy constructor, I just wanted you guys to get an idea of my layout
overloaded assignment operator
List & List::operator=(const List &rightSide)
{
if(this != &rightSide)
{
this->~List();
}
NodePointer ptr = rightSide.first;
NodePointer cptr = ptr;
while(ptr != NULL)
{
cptr->next = new Node(ptr->data);
cptr = cptr->next;
ptr = ptr->next;
}
return *this;
}
this is my copy constructor
List::List(const List &source)
{
NodePointer ptr = source.first;
NodePointer cptr;
if(ptr == NULL)
{
cerr << "Bad allocation, empty list" << endl;
exit(1);
}
while(ptr != NULL)
{
cptr = new Node(ptr->data);
cptr->next = ptr->next;
ptr = ptr->next;
}
}

Simple class won't work in C++

I have a question regarding classes in C++. I just wrote my first class by the help of my book and the exercise goes as follow:
Write a class book with a name, author and publisher. Make an object with hardcoded given text in the main. Let the book show by the use of the ToString() function. Do not leave the constructor empty and make use of the this-> pointer.
I have 0 errors in my compiler but it shows nothing and ends immediatly (my program), can somebody explain what I've done wrong and why the compiler hasn't seen my mistake?
I also have tried making an object on the heap but also won't work.
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
class Book
{
private:
string name;
string author;
string publisher;
public:
Book(string name, string author, string publisher)
{
this->name=name;
this->author=author;
this->publisher=publisher;
}
~Book(void)
{
}
string getName();
string getAuthor();
string getPublisher();
void setName(string name);
void setAuthor(string author);
void setPublisher(string publisher);
string toString();
};
string Book::getName()
{
return name;
}
string Book::getAuthor()
{
return author;
}
string Book::getPublisher()
{
return publisher;
}
void Book::setName(string name)
{
this->name=name;
}
void Book::setAuthor(string author)
{
this->author=author;
}
void Book::setPublisher(string publisher)
{
this->publisher=publisher;
}
string Book::toString()
{
stringstream ss;
ss << "Name of the book: " << name << endl;
ss << "Author of the book: " << author << endl;
ss << "The book has been published by: " << publisher << endl;
return ss.str();
}
int main()
{
Book b1=Book("The lone child","Bryan Addams", "Publishers INC");
b1.toString();
return 0;
}
You are never actually printing the return value of b1.toString(), so of course there is no output. Capturing the return value of toString(); and then printing it works.
int main () {
Book b1 = Book( "The lone child", "Bryan Addams", "Publishers INC");
string s = b1.toString();
cout << s << "\n";
return 0;
}
Or just printing it directly, as in:
int main () {
Book b1 = Book( "The lone child", "Bryan Addams", "Publishers INC");
cout << b1.toString() << "\n";
return 0;
}
You program works fine. You just dont print anything. You call
b1.toString();
Which only returns a string. Try replacing it with
cout << b1.toString();
Instead of returning ss.str in the string toString() function,
You should print it there.
string Book:toString(){
...
cout << ss.str;
...
}

non-portable way to find exception type in catch (...) for g++

Related questions:
Determining exception type after the exception is caught?
How can I determine the current exception in a catch (...) block?
This question differs because I don't care about portability. I'm interested in code specifically for g++ or perhaps even specific versions of g++ (4.6.3). It will not be used in production.
I'm dealing with legacy code that has thousands of throw statements with perhaps hundreds of thrown types. This code runs on nearly 1000 machines and catches about 40 throws per day. It is not repeatable.
At the outside layer, I can do a try { /.../ } catch (...) { /* caught it */ } and see that an exception was thrown. But I have not been able to find the type of the exception, let alone the location it is thrown from.
I believe the information must be available because code like the following works and prints "Y":
#include <iostream>
using namespace std;
struct X {};
struct Y {};
struct Z {};
int main(int, char **) {
try {
//...
throw Y();
//...
} catch (...) {
cout << "Caught unknown" << endl;
try {
throw;
} catch (const X &x) {
cout << "X" << endl;
} catch (const Y &y) {
cout << "Y" << endl;
} catch (const Z &z) {
cout << "Z" << endl;
}
}
}
Are there any [non-portable|dirty|nasty|ugly]* tricks to identify the exception type under g++ in a catch (...)?
Here's what I use:
#include <cxxabi.h>
using std::string;
string deMangle(const char* const name)
{
int status = -1;
char* const dem = __cxxabiv1::__cxa_demangle(name, 0, 0, &status);
const string ret = status == 0 ? dem : name;
if (status == 0)
free(dem);
return ret;
}
string getGenericExceptionInfo()
{
const std::type_info* t = __cxxabiv1::__cxa_current_exception_type();
char const* name = t->name();
return deMangle(name);
}
Usage:
catch (...)
{
std::cerr << "caught: " << getGenericExceptionInfo() << std::endl;
}