std::list iterator - c++

The following code instead of returning a pointer back to an audioResource it returns
something else which is invalid, i've gone through with a debugger and the problem is with this line
return *list_it;
Here is my function:
AudioResource* AudioManager::getResource(const unsigned int ID)
{
std::list<AudioResource*>::iterator list_it;
for(list_it = m_resources.begin(); list_it!= m_resources.end(); list_it++)
{
if((*list_it)->getID()==ID)
{
std::cout<<*(*list_it)->getFileName();
return *list_it;
}
}
return nullptr;
}
O and I have tried putting it as (*list_it) but i got the same results =s
How it is populated...
Resource* AudioManager::addResource(const unsigned int ID,
const std::string fileName, const unsigned int scope,
const std::string type)
{
AudioResource* temp;
if(type == "AUDIO_TYPE_SAMPLE")
{
temp = new AudioResource(ID,fileName,scope,
RESOURCE_AUDIO,AUDIO_TYPE_SAMPLE);
m_resources.push_back(temp);
}
else if(type == "AUDIO_TYPE_STREAM")
{
temp = new AudioResource(ID,fileName,scope,
RESOURCE_AUDIO,AUDIO_TYPE_STREAM);
m_resources.push_back(temp);
}
return temp;
}
call to get resource
cout<<AudioManager::getInstance()->getResource(IDnum)->getFileName();

If type is neither of the two values an uninitialized pointer is added to m_resources:
AudioResource* temp;
if(type == "AUDIO_TYPE_SAMPLE")
{
temp = new AudioResource(ID,fileName,scope,RESOURCE_AUDIO,AUDIO_TYPE_SAMPLE);
}
else if(type == "AUDIO_TYPE_STREAM")
{
temp = new AudioResource(ID,fileName,scope,RESOURCE_AUDIO,AUDIO_TYPE_STREAM);
}
m_resources.push_back(temp);
Initialize temp to NULL and only add to m_resources if temp != NULL.
Also, the function returns the same uninitialized pointer.

You return nullptr in case the ID doesn't exist, but you never check against it at the call site, which will give you a null pointer access if the ID doesn't exist and which will likely create problems.
AudioManager::getInstance()->getResource(IDnum)->getFileName();
Change that to
AudioResource* res = AudioManager::getInstance()->getResource(IDnum);
if(res)
std::cout << res->getFileName();

Related

char changing after returned

This is an attempted solution of a problem on codefights: https://codefights.com/interview-practice/task/FwAR7koSB3uYYsqDp
My BFS function is not returning the correct character despite me printing right before the return and seeing the correct character in the console. It seems the chracter is being mutated for some reason. When I change the function signature to have a std::string return value, the program crashes. I have no clue what I'm doing wrong. Is it possibly due to lack of freeing pointers or something?
typedef struct proTree{
char value;
proTree* left;
proTree* right;
} proTree;
char BFS(std::vector<proTree*> vec, int currLevel, int level, int pos){
if (currLevel == level){
if (vec[pos-1]->value == 'E'){
return 'E';
} else {
return 'D';
}
}
std::vector<proTree*> newVec;
for (int i=0; i<vec.size(); i++){
newVec.push_back(vec[i]->left);
newVec.push_back(vec[i]->right);
}
BFS(newVec, currLevel+1, level, pos);
}
void createTree(proTree* root, int currLevel, int level){
if (currLevel == level) return;
proTree* eTree = new proTree();
eTree->value = 'E';
proTree* dTree = new proTree();
dTree->value = 'D';
if (root->value=='E'){
root->left = eTree;
root->right = dTree;
} else {
root->left = dTree;
root->right = eTree;
}
createTree(eTree, currLevel+1, level);
createTree(dTree, currLevel+1, level);
}
std::string findProfession(int level, int pos) {
proTree* eTree = new proTree();
eTree->value = 'E';
createTree(eTree, 0, level);
std::vector<proTree*> vec = {eTree};
char result = BFS(vec, 0, level, pos);
if (result == 'E'){
return "Engineer";
} else {
return "Doctor";
}
}
BFS does not return anything (actually returned value is undefined) because last function line is missing return and the value of recursive function invocation is lost. It should be:
return BFS(newVec, currLevel+1, level, pos);
You should pay attention to compilation warnings. In this case compiler should've definitely complained about "missing return in function returning non-void" or something similar.

C++ return a const pointer inside a none const pointer function

I have coded this function to find the shallowest leaf in binary search tree it is not the best but it does the job, the leaf have to be returned after it have been found.
it is a necessary condition not to change the function prototype.
my problem is pointed by a comment below
The problem is i am returning a const Pointer inside a none const pointer function, i look before posting the question, all of the question where functions inside of classes, I have not studied them so I don't know if it is the same for functions outside of classes, is there any workaround for the problem ?
struct Node {
int _data;
struct Node *_left;
struct Node *_right;
};
//-----------------------------------------------------------------------------------
struct Node *min_depth_leaf(const struct Node *root, int &depth) {
int left_depth;
int right_depth;
if (root == NULL) {
depth = INT32_MAX;
return NULL;
} else if (root->_left == NULL && root->_right == NULL) {
depth = 0;
return root;//<-------------- The problem lays here
} else if (root->_left != NULL || root->_right != NULL) {
struct Node *left_node = min_depth_leaf(root->_left, left_depth);
struct Node *right_node = min_depth_leaf(root->_right, right_depth);
if (right_depth < left_depth) {
right_depth += 1;
depth = right_depth;
return right_node;
} else {
left_depth += 1;
depth = left_depth;
return left_node;
}
}
return NULL;
}
Two ways can be used. The first will help maintain a good project and the second will propagate undefined behaviours , giving an unstable software that behaves differently in the same situatuion.
The first way is to return a copy of the const Node, thus allowing the API user of min_depth_leaf to modify the returned copy value, without modifying the original value in the tree, code will be like:
#include<cstdlib>
struct Node {
int _data;
struct Node *_left;
struct Node *_right;
};
//-----------------------------------------------------------------------------------
struct Node *min_depth_leaf(const struct Node *root, int &depth) {
int left_depth;
int right_depth;
if (root == NULL) {
depth = INT32_MAX;
return NULL;
} else if (root->_left == NULL && root->_right == NULL) {
depth = 0;
// return a copy
Node * p = new Node();
p->_data=root->_data;
p->_left = root->_left;
p->_right = root->_right;
return p;
} else if (root->_left != NULL || root->_right != NULL) {
struct Node *left_node = min_depth_leaf(root->_left, left_depth);
struct Node *right_node = min_depth_leaf(root->_right, right_depth);
if (right_depth < left_depth) {
right_depth += 1;
depth = right_depth;
return right_node;
} else {
left_depth += 1;
depth = left_depth;
return left_node;
}
}
return NULL;
}
The other way (to be avoided) is to cast the const value to non const, causing undefined behaviors (UB), for example:
If the API user deletes the returned Node from min_depth_leaf that is returned it will be deleted from the tree.
if the API user creates the tree on stack in a function f1() and then gets the result of the min_depth_leaf in another function f2(), he will be surprised that as soon as f2() ends, the returned node will be deleted from stack, even though f1() is still not ended, so f1() will get garbage when accessing it .
This way is by using const_cast
return const_cast<Node *>(root); //never use this
Without changing the function's signature the only way to solve this problem is with const_cast:
return const_cast<Node*>(root);
Since your code looks like C rather than C++ to me, a C-style cast may be more appropriate:
return (struct Node*)root;
In any case changing the function signature is a way cleaner approach. If you make your function a template, it will work with both const and non-const nodes:
template<typename T> T* min_depth_leaf(T* root, int &depth)

Extending python3, how does the garbage collection work

I'm making my own PriorityQueue in C as a python module. I read the basics of python ownership and reference system, so I thought I'd do the following:
In push(): Accept an priority(int) and an object to be saved. Increment the reference count on the object to be saved, since we will be keeping that.
In pop(): Delete the object from my priorityqueue, but don't decrement the reference counter, since that might destroy the object. Instead I transfer my reference ownership to the python function calling my function.
This seemed to work at first hand. But when actually using it in an application I get the following error:
Fatal Python error: GC object already tracked
What does this mean? The stacktrace is not useful at all, it's all inside python files I don't recognize(sre_parse and apport_python_hook).
Just for clarity, these are my C push and pop functions:
(self->heap[index]->key is the priority of the element at that index
self->heap[index]->value is the object)
PyObject* pop(CDSHeap *self) {
//If there aare no elements
if (self->heap[0].value == 0 || self->end == 0) {
Py_RETURN_NONE;
}
//If there is only one element
if (self->end == 1) {
PyObject* result = self->heap[0].value;
self->heap[0].key = 0;
self->end = 0;
return result;
}
//Two or more elements:
//First save the result:
PyObject* result = self->heap[0].value;
//Get the last element, and place it at the top
while (self->heap[self->end].value == 0) self->end--;
self->heap[0].value = self->heap[self->end].value;
self->heap[0].key = self->heap[self->end].key;
self->heap[self->end].value = 0;
//Reheapify the heap
int ptr = 0;
while (self->end >= ptr) {
if (self->heap[ptr*2+1].value != 0 && self->heap[ptr*2+1].key < self->heap[ptr].key
&& (self->heap[ptr*2+2].value == 0 || self->heap[ptr*2+1].key <= self->heap[ptr*2+2].key)) {
swapElement(self->heap, ptr, ptr*2+1);
ptr = ptr*2+1;
}else
if (self->heap[ptr*2+2].value != 0 && self->heap[ptr*2+2].value < self->heap[ptr].value) {
swapElement(self->heap, ptr, ptr*2+2);
ptr = ptr*2+2;
} else {
break;
}
}
return result;
}
PyObject* push(CDSHeap *self, PyObject* args) {
int k;
PyObject *obj;
if (!PyArg_ParseTuple(args, "iO",&k, &obj)){
return NULL;
}
Py_INCREF(obj);
//Add the element to the end of the heap
self->heap[self->end].key = k;
self->heap[self->end].value = obj;
//Increment the size and reheapify
int ptr = self->end++;
while (ptr > 0) {
int parent = (ptr-1)/2;
if (self->heap[ptr].key < self->heap[parent].key) {
swapElement(self->heap, ptr, parent);
ptr = parent;
} else {
Py_RETURN_NONE;
}
}
Py_RETURN_NONE;
}

How do I return a Null Pointer in a function C++

I am currently working on a bit of code that will search within a vector of type Person (which I have defined in the code and will show if needed). If it finds the person, it returns their name. This is currently working, but if it does not find the person, it is supposed to return a Null pointer. The problem is, I cannot figure out how to make it return a Null pointer! It just keeps either crashing the program every time.
Code:
Person* lookForName(vector<Person*> names, string input)
{
string searchName = input;
string foundName;
for (int i = 0; i < names.size(); i++) {
Person* p = names[i];
if (p->getName() == input) {
p->getName();
return p; //This works fine. No problems here
break;
} else {
//Not working Person* p = NULL; <---Here is where the error is happening
return p;
}
}
}
You could use std::find_if algorithm:
Person * lookForName(vector<Person*> &names, const std::string& input)
{
auto it = std::find_if(names.begin(), names.end(),
[&input](Person* p){ return p->getName() == input; });
return it != names.end() ? *it : nullptr; // if iterator reaches names.end(), it's not found
}
For C++03 version:
struct isSameName
{
explicit isSameName(const std::string& name)
: name_(name)
{
}
bool operator()(Person* p)
{
return p->getName() == name_;
}
std::string name_;
};
Person * lookForName(vector<Person*> &names, const std::string& input)
{
vector<Person*>::iterator it = std::find_if(names.begin(), names.end(),
isSameName(input));
return it != names.end() ? *it : NULL;
}
If the name you are searching for is not at the first element, then you are not searching in the rest of the elements.
You need to do something like -
for (int i = 0; i<names.size(); i++){
Person* p = names[i];
if (p->getName() == input) {
return p;
// Placing break statement here has no meaning as it won't be executed.
}
}
// Flow reaches here if the name is not found in the vector. So, just return NULL
return NULL;
As Chris suggested, try using std::find_if algorithm.
Looks like you just have to return Null, nullptr, or 0.
codeproject
Just use following code:
return NULL;

Setting a pointer to null crashes my C++ program

I have a constructor, that receives a character pointer. If it is empty, I need to set its member variable to NULL, however, the program crashes on exit when I try to.
I have verified that it gets to the line where it sets it to NULL and that is the cause of the crash.
I've tried the following:
val = NULL;
val = 0;
val = "";
Those all cause a crash, however if I used:
val = new Char[1];
val = "o";
it didn't crash.
Is there something that I'm not doing?
Update:
Here is a quick update to my problem.
The destructor I'm using is:
~LField() {
if (val)
delete[] val;
}
If I take out:
if (val)
delete[] val;
then the program doesn't crash on exit with:
val = "";
Here is some more code as requested:
LField(int rowNumVal, int colNumVal, int widthVal, const char *valVal = "", bool canEditVal = true) {
if(strlen(valVal) > 0) {
//doesn't jump in here since valVal is empty
}
else {
val = ""; // this is where I'm trying to set a NULL value
}
}
LField(const LField &clone) {
if (val)
delete[] val;
val = new char[strlen(clone.val)];
strcpy(val, clone.val);
rowNum = clone.rowNum;
colNum = clone.colNum;
width = clone.width;
canEdit = clone.canEdit;
index = clone.index;
}
LField& operator=(const LField &lfieldobj) {
if (this != &lfieldobj) {
if (val)
delete[] val;
val = new char[strlen(lfieldobj.val)];
strcpy(val, lfieldobj.val);
rowNum = lfieldobj.rowNum;
colNum = lfieldobj.colNum;
width = lfieldobj.width;
canEdit = lfieldobj.canEdit;
index = lfieldobj.index;
}
return *this;
}
Modified:
LField(int rowNumVal, int colNumVal, int widthVal, const char *valVal = NULL, bool canEditVal = true) {
if(valVal != NULL) {
}
else {
val = NULL;
}
}
LField(const LField &clone) {
delete[] val;
if (clone.val != NULL) {
val = new char[strlen(clone.val) + 1];
strcpy(val, clone.val);
}
else
val = NULL;
rowNum = clone.rowNum;
colNum = clone.colNum;
width = clone.width;
canEdit = clone.canEdit;
index = clone.index;
}
LField& operator=(const LField &lfieldobj) {
if (this != &lfieldobj) {
delete[] val;
if (lfieldobj.val != NULL) {
val = new char[strlen(lfieldobj.val) + 1];
strcpy(val, lfieldobj.val);
}
else
val = NULL;
rowNum = lfieldobj.rowNum;
colNum = lfieldobj.colNum;
width = lfieldobj.width;
canEdit = lfieldobj.canEdit;
index = lfieldobj.index;
}
return *this;
}
~LField() {
delete[] val;
}
I've updated the code. Now val is either allocated memory with new[] or it is NULL, so there shouldn't be a problem with delete[]. However, it still crashes on exit.
In the copy constructor you try to delete[] an uninitialized pointer:
LField(const LField &clone) {
//good code here, then...
if (val) //<+ some random address here
delete[] val;//<-undefined behavior
}
just don't do that, skip the whole construct. The copy constructor is invoked on an unitilialized object, there're no resources to "free" yet.
Also you try to delete[] a string literal, that's undefined behavior. Try the following change:
LField(int rowNumVal, int colNumVal, int widthVal, const char *valVal = "", bool canEditVal = true) {
if(strlen(valVal) > 0) {
//doesn't jump in here since valVal is empty
}
else {
val = new char[1];
*val = 0;
}
}
also the following is a buffer overrun:
val = new char[strlen(whatever)]; <-forgot to +1 for the null terminator
strcpy(val, whatever);
also checking for a null pointer before delete[] is unnecessary - delete[] on a null pointer is legal and has no effect.
Oh dear, where to start??
a:
LField(const LField &clone) {
if (val)
delete[] val;
This is daft, as val is undefined. You will be calling delete[] on random memory.
b:
val = new char[strlen(clone.val)];
strcpy(val, clone.val);
c-type Strings need a null terminator. You need to new[] and additional byte.
Probably somewhere in your code you are trying to access(dereference) val which still refers to NULL.
Make sure no where in your code you are doing this
val=NULL; //in the constructor
//somewhere in your code
char ch= *val; //This would be Undefined Behavior
EDIT
You are calling delete[] on val whose value is ""(string literal), that is undefined behavior.
Some examples of UB
1)
char *p="hello";
delete p; //UB
delete []p; //UB
2)
char *p==new char[20]("Hello");
delete p; //UB
delete []p; //fine
3)
char *p=new char('a');
delete []p; //UB
delete p; //fine
Calling
delete[] NULL;
delete[] 0;
is ok, you don't even need the null-check.
But calling
delete[] "whatever";
is not OK since this char* wasn't allocated with new[].
Note that calling string function like strlen() like it is done in your constructor is illegal in a null reference.
You access val in your constructor before it is assigned the first time. This can also cause undefined behaviour.
I'm with Prasoon Saurav. The code you showed looks good, so the problem is somewhere else.
Try this:
Change it back to val = 0;
Remove all your code except the constructor, the destructor, and a declaration of an object of that class. Comment out everything else. I'd wager good repuation that it won't crash.
Slowly uncomment your other code and retry the program. When it crashes again, you've found the culprit.