Consider the following usage of smart pointer std::unique_ptr:
std::unique_ptr<char> sp(new(std::nothrow) char[sz]);
How can I check if the new was successful?
I have two options:
Method 1 - Check for bool value: if(!sp){}
Method 2 - Compare against null pointer: if(sp==nullptr){}
Example (source)
#include <iostream>
#include <memory>
using namespace std;
int main() {
constexpr long long sz = 1000000e10;
//raw pointer
auto ptr = new(std::nothrow) char[sz];
if(ptr==nullptr)
{
cout<<"ptr nullptr"<<endl;
}
//smart pointer
std::unique_ptr<char> sp(new(std::nothrow) char[sz]);
if(!sp)
{
cout<<"sp nullptr bool"<<endl;
}
if(sp==nullptr)
{
cout<<"sp nullptr =="<<endl;
}
return 0;
}
Output:
Success #stdin #stdout 0s 4396KB
ptr nullptr
sp nullptr bool
sp nullptr ==
Clearly both Method 1 and Method 2 seem to work.
I would however like to read from an authoritative source (C++ standard, msdn, gcc documentation) that this indeed is the correct way.
I, as an authoritative source, can confirm that both ways are indeed correct.
Just kidding: std::unique_ptr's operator ==(std::nullptr_t) and operator bool are overloaded to perform what you'd expect from a pointer, so yes, both are correct, although method 1 is more idiomatic.
Related
Under what circumstances might you want to use multiple indirection (that is, a chain of pointers as in Foo **) in C++?
Most common usage as #aku pointed out is to allow a change to a pointer parameter to be visible after the function returns.
#include <iostream>
using namespace std;
struct Foo {
int a;
};
void CreateFoo(Foo** p) {
*p = new Foo();
(*p)->a = 12;
}
int main(int argc, char* argv[])
{
Foo* p = NULL;
CreateFoo(&p);
cout << p->a << endl;
delete p;
return 0;
}
This will print
12
But there are several other useful usages as in the following example to iterate an array of strings and print them to the standard output.
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
const char* words[] = { "first", "second", NULL };
for (const char** p = words; *p != NULL; ++p) {
cout << *p << endl;
}
return 0;
}
IMO most common usage is to pass reference to pointer variable
void test(int ** var)
{
...
}
int *foo = ...
test(&foo);
You can create multidimensional jagged array using double pointers:
int ** array = new *int[2];
array[0] = new int[2];
array[1] = new int[3];
One common scenario is where you need to pass a null pointer to a function, and have it initialized within that function, and used outside the function. Without multplie indirection, the calling function would never have access to the initialized object.
Consider the following function:
initialize(foo* my_foo)
{
my_foo = new Foo();
}
Any function that calls 'initialize(foo*)' will not have access to the initialized instance of Foo, beacuse the pointer that's passed to this function is a copy. (The pointer is just an integer after all, and integers are passed by value.)
However, if the function was defined like this:
initialize(foo** my_foo)
{
*my_foo = new Foo();
}
...and it was called like this...
Foo* my_foo;
initialize(&my_foo);
...then the caller would have access to the initialized instance, via 'my_foo' - because it's the address of the pointer that was passed to 'initialize'.
Of course, in my simplified example, the 'initialize' function could simply return the newly created instance via the return keyword, but that does not always suit - maybe the function needs to return something else.
If you pass a pointer in as output parameter, you might want to pass it as Foo** and set its value as *ppFoo = pSomeOtherFoo.
And from the algorithms-and-data-structures department, you can use that double indirection to update pointers, which can be faster than for instance swapping actual objects.
A simple example would be using int** foo_mat as a 2d array of integers.
Or you may also use pointers to pointers - lets say that you have a pointer void* foo and you have 2 different objects that have a reference to it with the following members: void** foo_pointer1 and void** foo_pointer2, by having a pointer to a pointer you can actually check whether *foo_pointer1 == NULL which indicates that foo is NULL. You wouldn't be able to check whether foo is NULL if foo_pointer1 was a regular pointer.
I hope that my explanation wasn't too messy :)
Carl: Your example should be:
*p = x;
(You have two stars.) :-)
In C, the idiom is absolutely required. Consider the problem in which you want a function to add a string (pure C, so a char *) to an array of pointers to char *. The function prototype requires three levels of indirection:
int AddStringToList(unsigned int *count_ptr, char ***list_ptr, const char *string_to_add);
We call it as follows:
unsigned int the_count = 0;
char **the_list = NULL;
AddStringToList(&the_count, &the_list, "The string I'm adding");
In C++ we have the option of using references instead, which would yield a different signature. But we still need the two levels of indirection you asked about in your original question:
int AddStringToList(unsigned int &count_ptr, char **&list_ptr, const char *string_to_add);
Usually when you pass a pointer to a function as a return value:
ErrorCode AllocateObject (void **object);
where the function returns a success/failure error code and fills in the object parameter with a pointer to the new object:
*object = new Object;
This is used a lot in COM programming in Win32.
This is more of a C thing to do, in C++ you can often wrap this type of system into a class to make the code more readable.
I'm porting an old C++ program to modern C++. The legacy program uses new and delete for dynamic memory allocation. I replaced new with std::unique_ptr, but I'm getting compilation error when I try to reset the unique_ptr.
Here is the striped down version of the program. My aim is to get rid of all the naked new.
#include <memory>
enum class Types {
ONE,
TWO,
};
// based on type get buffer length
int get_buffer_len(Types type) {
if(type == Types::ONE) return 10;
else if(type == Types::TWO) return 20;
else return 0;
}
int main() {
Types type = Types::ONE;
std::unique_ptr<char[]> msg{};
auto len = get_buffer_len(type);
if(len > 0) {
msg.reset(std::make_unique<char[]>(len));
}
// based on type get the actual message
if(type == Types::ONE) {
get_message(msg.get());
}
}
I get the following compilation error:
error: no matching function for call to 'std::unique_ptr<char []>::reset(std::__detail::__unique_ptr_array_t<char []>)'
| msg.reset(std::make_unique<char[]>(len));
| ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you look at the reset function, it takes a ptr to memory, not another unique ptr:
// members of the specialization unique_ptr<T[]>
template< class U >
void reset( U ptr ) noexcept;
This function is designed to allow you to reset a unique pointer and simultaneously capture memory that you intend to manage with said unique_ptr. What you are looking to do is assign an r-value unique_ptr to ann existing unique_ptr (msg), for which c++ also has an answer:
unique_ptr& operator=( unique_ptr&& r ) noexcept;
Move assignment operator. Transfers ownership from r to *this as if by calling reset(r.release()) followed by an assignment of get_deleter() from std::forward(r.get_deleter()).
So you can instead just do:
msg = std::make_unique<char[]>(len);
if we have a code like this :
void g(int *n){
int m=n[1];
n= null ;
}
void main(){
int ∗ p = (int∗)malloc(10 ∗ sizeof (int));
int * q= p;
g(p);
}
so we know if we overload malloc, calloc , realloc ,new ,free and delete functions we can track first pointer that create or delete with this functions(p pointer in above example ) but how can i find and track other pointers and functions that using this allocated memory ? ( q pointer and g function in above example ) .should i overload Assignment statement and function call ? if yes how ? in other words i want to know live objects and last used time and location of an allocated memory too .
i want to implement an custom memory leak detection tools so i need to find all objects and pointer that using an allocated memory before report it that's leak or not .
What you're talking about is called reference counting. Searching stackoverflow for this topic gives you these results:
What is a smart pointer and when should I use one?
How does a reference-counting smart pointer's reference counting work?
what exactly reference counting in c++ means?,
The standard template library already has a std::shared_ptr which does that.
We need to keep track of the lifecycle of the resource, this is possible by controlling the creation, the copying and the deletion. If you do it without using a class, you'll end up with some functions, a state variable and a global variable. This is not very effective in keeping the concept of the shared resource in the focus of the user's mind. One tends to forget that one is using a shared resource because one sees a naked pointer and tends to use it like one, which would disregard the provided shared-pointer functionality.
If you were to encapsulate the functionality in a class, you should want to implement the concept for all types i.e. you should want to use templates. one way would be this:
#include <vector>
#include <stdexcept>
#include <cstdlib>
#ifndef SHARED_PTR_H
#define SHARED_PTR_H
template<class Tres_t>
class shared_pointer
{
// members
Tres_t* data_;
static std::vector<std::size_t> ref_counts_;
std::size_t ref_index_ = {};
public:
// lifecycle
shared_pointer() = delete;
shared_pointer(const std::size_t& size)
: data_{nullptr}
{
data_ = static_cast<Tres_t*>(std::malloc(size * sizeof(Tres_t)));
ref_counts_.push_back(1);
ref_index_ = ref_counts_.size() - 1;
}
shared_pointer(const shared_pointer& rhs)
: data_{rhs.data_}, ref_index_{rhs.ref_index_}
{
if (ref_index_ >= ref_counts_.size())
{
throw std::runtime_error("shared_pointer_ctor_index_error");
}
++ref_counts_[ref_index_];
}
shared_pointer(shared_pointer&& rhs)
: data_{rhs.data_}, ref_index_{rhs.ref_index_} {}
shared_pointer& operator=(const shared_pointer& rhs)
{
data_ = rhs.data_;
ref_index_ = rhs.ref_index_;
if (ref_index_ >= ref_counts_.size())
{
throw std::runtime_error("shared_pointer_ctor_index_error");
}
++ref_counts_[ref_index_];
}
shared_pointer& operator=(shared_pointer&& rhs)
{
data_ = rhs.data_;
ref_index_ = rhs.ref_index_;
}
~shared_pointer()
{
if (ref_counts_[ref_index_] == 0)
{
std::logic_error("shared_point_dtor_reference_counting_error");
}
--ref_counts_[ref_index_];
if (ref_counts_[ref_index_] == 0)
{
std::free(data_);
}
}
// main functionality
Tres_t* data()
{
return data_;
}
const Tres_t* data() const
{
return data_;
}
};
template<class Tres_t>
std::vector<std::size_t> shared_pointer<Tres_t>::ref_counts_ = {};
#endif
I've tested this code only rudimentarily so I'll leave it to you to test and improve it.
I am trying to add SALto my code... i worked according msdn and found bug in msdn examples, don't know how to deal with it.
Here litle changed example "Output of pointer to caller (Example: The Outptr Annotation)" from Understanding SAL
Outptr is used to annotate a parameter that's intended to return a
pointer. The parameter itself should not be NULL, and the called
function returns a non-NULL pointer in it and that pointer points to
initialized data.
My code:
#include "stdafx.h"
#include "assert.h"
void GoodOutPtrCallee(_Outptr_ int **pInt)
{
int *pInt2 = new int;
if (*pInt != NULL)
{
*pInt2 = 1;
}
else
{
*pInt2 = 2;
}
*pInt = pInt2;
}
int _tmain(int argc, _TCHAR* argv[])
{
int* nullValue = NULL;
GoodOutPtrCallee(&nullValue);
assert(*nullValue == 2);
int someValue = 22;
int* someValuePtr = &someValue;
GoodOutPtrCallee(&someValuePtr);
assert(*someValuePtr == 1);
return 0;
}
If i compile it in VS2013 with code alalysys enabled i got C6001: using uninitialized memory
for
if (*pInt != NULL)
row.
What is worng here in my annotation and how can i fix it?
Since you're reading from the value passed through the pointer parameter pInt you can't use _Outptr_ , as this describes a parameter that's only used as an output, not also as an input. Use _Inout_ instead.
You might want to reconsider using SAL. It's very poorly documented, and as a result I can't say with any certainty that _Inout_ is actually the best annotation to use here. All I know for sure is that it's best match I could find based on Microsoft's vague descriptions, and it gets rid of the warning. Of course so would not using an annotation.
EDIT: I was confused by similar variable names, pInt and pInt2.
You're probably should mark pInt as input and output, not just as output, because you're reading it's value to check whether it is NULL
Suppose I have this code. Your basic "if the caller doesn't provide a value, calculate value" scenario.
void fun(const char* ptr = NULL)
{
if (ptr==NULL) {
// calculate what ptr value should be
}
// now handle ptr normally
}
and call this with either
fun(); // don't know the value yet, let fun work it out
or
fun(something); // use this value
However, as it turns out, ptr can have all kinds of values, including NULL, so I can't use NULL as a signal that the caller doesn't provide ptr.
So I'm not sure what default value to give ptr now instead of NULL. What magic value can I use? Does anybody have ideas?
void fun()
{
// calculate what ptr value should be
const char* ptr = /*...*/;
// now handle ptr normally
fun(ptr);
}
Depending on your platform, a pointer is likely either a 32 or 64-bit value.
In those cases, consider using:
0xFFFFFFFF or 0xFFFFFFFFFFFFFFFF
But I think the bigger question is, "How can NULL be passed as a valid parameter?"
I'd recommend instead having another parameter:
void fun(bool isValidPtr, const char* ptr = NULL)
or maybe:
void fun( /*enum*/ ptrState, const char* ptr = NULL)
I agree with all the other answers provided, but here's one more way of handling that, which to me personally looks more explicit, if more verbose:
void fun()
{
// Handle no pointer passed
}
void fun(const char* ptr)
{
// Handle non-nullptr and nullptr separately
}
You should use the nullptr for that. Its new in the C++11 standart. Have a look here for some explanation.
Using overloaded versions of the same function for different input is best, but if you want to use a single function, you could make the parameter be a pointer-to-pointer instead:
void fun(const char** ptr = NULL)
{
if (ptr==NULL) {
// calculate what ptr value should be
}
// now handle ptr normally
}
Then you can call it like this:
fun();
.
char *ptr = ...; // can be NULL
fun(&ptr);
If you want a special value that corresponds to no useful argument, make one.
header file:
extern const char special_value;
void fun(const char* ptr=&special_value);
implementation:
const char special_value;
void fun(const char* ptr)
{
if (ptr == &special_value) ....
}
1?
I can't imagine anyone allocating you memory with that address.