I want to write a generic centralized null-checker API for pointer type objects. I want to populate a list of my input pointer objects and call the null-checker API to scan through the list and validate if any pointer object is having NULL value. For this, I need to store varying levels of pointers in a single generic variable. How can I do that in C++ ?
template<typename type>
bool check(type& t)
{
return false;
}
template<typename type>
bool check(type* t)
{
return true;
}
int main()
{
char** doubleCharPointer = NULL;
char* charPointer = "charPointer";
doubleCharPointer = &charPointer;
char** temp = doubleCharPointer;
char* temp1 = NULL;
int count = 0;
if(!check(temp))
{
cout << "\nNot a pointer" << endl;
return 0;
}
temp1 = *temp;
count++;
if(!check(temp1))
{
cout << "\nPointer level : " << count << endl;
return 0;
}
count++;
cout << "\nPointer level : " << count << endl;
}
This is my null-checker prototype. It is very static at the moment. But I wanted to extend it to support any level of pointer checking. For that I need "temp" to be able to hold any level of pointer so that I can run an infinite while loop till all the levels of the input pointer is consumed and validated. How can I do that ? Please help.
I don't believe that there is a direct solution to this without knowing the exact numbers of levels. Let's say that you can advance level by level checking every level if it's NULL or not, however the main problem is that you don't know how far you must search, so in the end if you just go from address to address you may end up finding a NULL pointer or never ending your verification loop because you don't have a stop condition.
By doing this you may also access an unallocated memory address which may throw or not an exception, so you can't either use this thrown exception as a stop condition.
I think you want
template<typename T>
bool check_ptr_not_null(const T&)
{
return true; // not a pointer
}
template<typename T>
bool check_ptr_not_null(T* t)
{
return (t != nullptr) && check_ptr_not_null(*t);
}
Live Demo
Disclaimer: Do not up-vote this answer (dirty hack)
Expanding on A-B's answer, this is the best I can get to at the moment:
template<typename T>
bool notnull(T const *t, int level) {
while (level-- > 1) {
if (t == NULL)
return false;
t = (T const *)*t;
}
return t != NULL;
}
Note that this will induce some compiler warnings because of the line t = (T const *)*t so I guess this is unsafe. A cleaner way of doing this is just define some macros instead:
#define NOTNULL_P1(x) (x != NULL)
#define NOTNULL_P2(x) ((x != NULL) && NOTNULL_P1(*x))
#define NOTNULL_P3(x) ((x != NULL) && NOTNULL_P2(*x))
#define NOTNULL_P4(x) ((x != NULL) && NOTNULL_P3(*x))
#define NOTNULL_P5(x) ((x != NULL) && NOTNULL_P4(*x))
Related
I am trying to write a BST which performs common operations, Insertion, Deletion, Search, and traversals.
The problem I have found is that the created tree works perfectly when it is assigned to use non-primitive data types, For exmple: user defined struct, classes and C++ stl classes (as std::string)
But when I use int, double_t, int64_t and so, it throws an exception.
~BinaryNode()
{
if (left_ != NULL)
Deleting(left_);
if (right_ != NULL)
Deleting(right_);
//The exception occurs here when the primitive data type
//is attempted to be deallocated
}
//Using preorder to delete this tree recursively
void Deleting(BinaryNode<T> *node)
{
if (node == NULL) return;
if (node->left_ != NULL)
delete node->left_;
if (node->right_ != NULL)
delete node->right_;
node->left_ = node->right_ = NULL;
delete node;
}
I had made many tests, checking the integrity between nodes and that's not the problem. Because, As I said, the problem is when the destructor reaches its end.
When I used the debugger I saw that a std::string calls its destructor and is correctly deallocated. But with primitive types it throws an exception of type:
Exception has occurred.
Trace/breakpoint trap
Thanks Beforehand.
Edit:
I am testing it as:
int main()
{
BinarySearchTree<uint64_t> bst(
[](const uint64_t &t1, const uint64_t &t2) -> int8_t {
if (t1 == t2) return 0;
if (t1 > t2) return 1;
else return -1;
});
//performance slow down because there are (20000^2)/2 operations
//to do. This is not a Self Balanced tree, so it is expected
//it ends having worst performance than a singly linked list
for (size_t i = 0; i <= 200; i++)
// i <= 20000 causes error
// i <= 200 or i <= 2000 works perfect
{
bst.Insert(i);
std::cout << "i:" << i << std::endl;
}
std::cout << bst.Size() << std::endl;
bst.Clear();//this generates the error. [When i <= 20000]
}
Definition of Insert
virtual bool Insert(const T &t)
{
if (this->root_ == NULL)
{
this->root_ = new BinaryNode<T>(t);
return true;
}
return Insert(t, this->root_);
}
virtual bool Insert(const T& t, BinaryNode<T> *node)
{
if (this->comparing_(t, node->t_) > 0)
if (node->left_ == NULL)
{
node->left_ = new BinaryNode<T>(t);
this->size_++;
}
else Insert(t, node->left_);
else if (this->comparing_(t, node->t_) < 0)
if (node->right_ == NULL)
{
node->right_ = new BinaryNode<T>(t);
this->size_++;
}
else Insert(t, node->right_);
else return false; //if there is such element
return true; //if it was successfully inserted
}
This is the definition of Clear
virtual void Clear()
{
delete root_;
root_ = NULL;
}
Note: comparing_ is a lambda.
I think that this is a recursion error.
I found that the error was produced due to a stack overflow error. Why? Because the stack of calls was adding as many calls as nodes were at an unbalanced side of the tree.
Due the nature of an unbalanced binary search tree this happens, there is a limit for recursion. I tried adding 20.000 and 200.000 elements into a AVLTree and it worked fine due the self balancing procedure, because it ensures the tree to have a height O(ln(n))
As I can't see the node class so according to my understanding:
The data types like int can't be assigned NULL.
Need to implement stack using array only, methods: push, pop, print.
The task itself:
Implement stack using only array. The only time compiler should allocate memory is through set_size function.
The current code version works good enough, but I'm looking for ways to improve it's exec-time / complexity / readability etc. Any ideas?
Thank you in advance.
#include <vector>
#include <string>
template <class T>
class Stack
{
int size = 0;
T* Array;
int top = 0;
public:
Stack(size_t Size);
~Stack()
{
delete[] Array;
}
void push(T element);
void pop();
void print();
};
template <class T>
Stack<T>::Stack(size_t Size)
{
size = Size;
top = -1;
Array = new T[size];
}
template <class T>
void Stack<T>::push(T element)
{
if (top >= (size - 1))
{
std::cout << "overflow" << std::endl;
}
else
{
Array[++top] = element;
}
}
template <class T>
void Stack<T>::pop()
{
if (top < 0)
{
std::cout << "underflow" << std::endl;
}
else
{
std::cout << Array[top--] << std::endl;
}
}
template <class T>
void Stack<T>::print()
{
if (top == -1)
{
std::cout << "empty" << std::endl;
}
int i = top;
while (i > -1)
{
std::cout << Array[i--] << " ";
}
std::cout << std::endl;
}
template <class T>
Stack<T> set_size(int Size)
{
return Stack<T>(Size);
}
int main()
{
auto stack = set_size<std::string>(5);
stack.push("hello");
stack.push("hi");
stack.push("hey");
stack.push("greetings");
stack.push("welcome");
stack.print();
stack.pop();
stack.pop();
stack.print();
return 0;
}```
Your main problem comes from the type conversion between your stack pointer top to your stack size size.
top is an int, which is a signed type.
size_t is an unsigned integral type.
When testing (top >= (size - 1)), top is converted to an unsigned int and then considered as UINT_MAX instead of -1, which is always >= to any other unsigned int.
You can either use a size_t as your stack pointer, which means that you cannot use negative value, or convert (size - 1) to a signed value before comparing to top (but this last solution means that you must ensure that the size you specify as a size_t is not too big to be converted to a signed int).
Your print function has also two issues:
in your first test, you assign -1 to top instead of comparing the values
you change your top stack pointer, so that you stack is in an inconsistant state after a call to print()
Your branch predictions are possibly not optimal. You should inspect the resulting assembly to see if the prediction bets on the if rather than on else in your if...else constructs (it will probably predict the if and in this case you should put the common case in the if).
You should pass the arguments by reference and not by value. It doesn't matter in case of simple integers but if your T becomes something more complex, it will result in redundant copy upon push.
Symptoms
I was investigating using the chromium stack_container set specifically the StackString. I made a test program with the following:
#include <chromium/base/stack_container.h>
int main() {
StackString<300> s;
return 0;
}
This should create space on the stack and the string would reserve this space.
I was surprised to find, when i added some breakpoints to allocate in StackAllocator that the stack buffer is never returned to anyone. Ie, the general purpose allocater is always called:
pointer allocate(size_type n, void* hint = 0) {
if (source_ != NULL && !source_->used_stack_buffer_
&& n <= stack_capacity) {
source_->used_stack_buffer_ = true; // source_ is always NULL
return source_->stack_buffer(); // and so this is never returned.
} else {
return std::allocator<T>::allocate(n, hint); // This is always called.
}
}
Problem
After further investigation, i found that this is because when the std::basic_string type is created (as part of the construction of StackString) the VisualC++ implementation stores the allocater into some pair. Then when needing to use it, it copies it into a proxy:
void _Alloc_proxy()
{ // construct proxy
typename _Alty::template rebind<_Container_proxy>::other
_Alproxy(_Getal()); // Copies the allocator!
_Myproxy() = _Unfancy(_Alproxy.allocate(1)); // NOTE this for a later point.
...
The copy constructor of the StackAllocator will set the copies stack pointer to NULL. Hence the StackString could never work.
Furthermore, if the StackStringdidnt have this problem, it immediatly allocates space of 1, meaning after you add anything, it will quickly grow and suffer the same problem anyway.
Questions
Is this a bug, and if so by whom, VisualC++ or chromium?
If the first symptom doesn't occur, wouldn't the second item be a problem for most compilers anyway?
It seems that StackString was removed from the Chromium project: https://bugs.chromium.org/p/chromium/issues/detail?id=709273
But it's rather not a bug but some kind of optimization for a small string.
Visual Studio 2015/2017 will allocate a 16-byte std::_Container_proxy in the heap when compiling in "Debug" even for an empty string.
In "Release", we won't use the heap memory for the StackString.
I tested it with this code:
#include <iostream>
#include <new>
#include "stack_container.h"
std::size_t memory = 0;
std::size_t alloc = 0;
void* operator new(std::size_t s) throw(std::bad_alloc) {
// Put breakpoint here
memory += s;
++alloc;
return malloc(s);
}
void operator delete(void* p) throw() {
--alloc;
free(p);
}
void PrintMem_Info()
{
std::cout << "memory = " << memory << '\n';
std::cout << "alloc = " << alloc << '\n';
}
int main()
{
StackString<256> str;
PrintMem_Info();
str->append("Hello World!");
PrintMem_Info();
str[0] = '1';
str[1] = '2';
}
And my solution is:
pointer allocate(size_type n, void* hint = 0) {
#if defined(_MSC_VER)
if (n > stack_capacity)
{
n = stack_capacity;
}
#endif // if defined(_MSC_VER)
if (source_ != nullptr && !source_->used_stack_buffer_
&& n <= stack_capacity) {
source_->used_stack_buffer_ = true;
return source_->stack_buffer();
}
else {
return std::allocator<T>::allocate(n, hint);
}
}
template<class Type>
int StringList<Type>::find(Type value)
{
int count = 0;
// Start of linked list
Node<Type> *current = head;
// Traverse list until end (NULL)
while (current != NULL)
{
// Increase counter if found
if (current->data == value)
{
count++;
}
// If not, move to the next node
current = current->next;
}
cout << value << " was found " << count << " times" << endl;
return 0;
// same function but using Recursive method
// Start of linked list
Node<Type> *current = head;
int count = 0;
// Thinking this is the base case, since its similar to the while loop
if (current == NULL)
{
return 0;
}
// same as the while loop, finding the value increase the count, or in this case just prints to console
if ((current->data == value))
{
cout << "Found match" << endl;
return 0;
}
else
{ // If it didnt find a match, move the list forward and call the function again
current = current->next;
return find(value);
}
}
the function is supposed to find the value searched and return how many times that certain value was in the linked list.
how can I turn the first method, which uses a while loop, into something that does the same thing but uses recursion?
For starters instead of the return type int it is better to use an unsigned type like for example size_t
You can use the following approach. Define two methods. The first one is a public non-static method find defined like
template<class Type>
size_t StringList<Type>::find( const Type &value ) const
{
return find( head, value );
}
The second one is a private static method with two parameters defined like
template<class Type>
static size_t StringList<Type>::find( Node<Type> *current, const Type &value )
{
return current == nullptr ? 0 : ( current->data == value ) + find( current->next, value );
}
In order to use recursion, you will need to change the signature of your find function (or add a new function with the different signature) to take a node pointer as a parameter:
template<class Type>
int StringList<Type>::find(Type value, Node<Type> *where)
{
if (where != nullptr)
{
// Do things
}
}
Then, when you traverse the list, you pass where->next to the function. Once you hit the end of the list, with a nullptr value, the stack unrolls.
A key aspect of recursion as that the function or method being used only has to process a single node of your container. It then calls itself with the next node to be processed until there are no more nodes. In order to make this work, that function needs the node to process as a parameter, which is where your current code runs into problems.
Keep in mind that the elegance and simplicity of recursion is not free. Every call that a method makes to itself eats up stack, so a sufficiently large container can result in a crash if the stack for your process is depleted.
how can I turn the first method, which uses a while loop, into
something that does the same thing but uses recursion?
The following would be closer to what you want. You really should provide an [MCVE] ... the lack of which forces many guesses and assumptions about your code.
// It looks like StringList is a class (I ignored template issues),
// and it appears that your class holds 'anchors' such as head
// StringList is probably the public interface.
//
// To find and count a targetValue, the code starts
// at the head node, and recurses through the node list.
// I would make the following a public method.
//
int StringList::findAndCountTargetValue(int targetValue)
{
int retVal = 0;
if (nullptr != head) // exists elements to search?
retVal = head->countTV(targetValue); // recurse the nodes
// else no match is possible
return(retVal);
}
// visit each node in the list
int Node::countTV(const int targetValue)
{
int retVal = 0; // init the count
if (data != targetValue) // no match
{
if(nullptr != next) // more elements?
retVal += next->countTV() // continue recursive count
}
else
{
std::cout << "Found match" << std::endl; // for diag only
retVal += 1; // because 1 match has been found
if(nullptr != next) // more elments
retVal += next->countTV(); // continue recursive count
}
return (retVal); // always return value from each level
}
I am trying to use STL list in a project but i have the following problem.
I want my list to store a struct. For example this one
struct mystruct
{
int x;
int y;
};
Then i am using an iterator to access every struct in the list like this.
list<mystruct> L;
list<mystruct>::iterator lit;
for(lit=L.begin();lit!=L.end();lit++)
{
if(lit->x==1) cout << "<NUM," << lit->x << "> ";
if(lit->y==2) cout << "<ID," << lit->y << "> ";
}
This works but i want to get one struct at a time so i made this func
mystruct Myclass::next(void)
{
if(lit!=L.end())
{
lit++;
}
return *lit;
}
but i get an error after running it and i cannot understand why this happens.
Any ideas what is going wrong?
mystruct Myclass::next(void)
{
if(lit!=L.end())
{
lit++;
}
return *lit;
}
You increment unless you already are at the end, but the dereferencing happens every time, regardless of if you are at the end or not. To help around that problem, consider returning a pointer, and then a 0 pointer if you are at the end.
mystruct* Myclass::next(void)
{
if(lit!=L.end() && ++lit != L.end())
{
// dereference to get the struct, and then return the address of the struct
return &*lit;
}
return 0;
// or nullptr in C++0x
}
And then check agains 0 (or nullptr) in the code where you use Myclass::next.
If you're writing next() that returns an object (rather than pointer), then I think you also need to write has_next() function which you should call to inspect if there is item in the list or not, before calling next(). Something like this:
bool has_next()
{
list<mystruct>::iterator temp = lit;
return ++temp != L.end();
}
mystruct Myclass::next(void)
{
if( !has_next())
{
throw "end of the list is reached";
}
++lit;
return *lit;
}
//usage
while(myClassInstance.has_next())
{
mystruct s = myClassInstance.next();
//work with s
}
Or if you decide to return pointer to mystruct from next(), then has_next() is not so needed. You can write this:
mystruct * Myclass::next(void)
{
++lit;
if( lit == L.end() )
return NULL;
return &(*lit);
}
The problem is here :
mystruct Myclass::next(void)
{
if(lit!=L.end())
{
lit++;
}
return *lit;
}
First how is lit defined?
Second, if lit is equal to L.end() you should return some default value, not dereference it, because if you do, you are causing an undefined behaviour. If you are lucky, your program will crash.