If I have the following code:
// objective C++ code .mm
id<MTLTexture> texture = ...;
void* ptr = (void*)CFBridgingRetain(texture);
share_ptr_with_native_code(ptr);
[texture do_stuff]; // is this valid?
// native code .cpp
void share_ptr_with_native(void* ptr)
{
ptr->do_stuff();
CFBridgingRelease(ptr);
}
Will texture be valid and retained by ARC again after the call to share_ptr_with_native()?
Other than various errors in your code snippet, yes, the line in question is valid. ARC continues to maintain its own strong reference to object while it's still in use in the top code, in addition to the one that you become responsible for. CFBridgingRetain() has a +1 effect on the retain count of the object, hence "retain" in its name.
Even everything said is right, it would be nicer if you change your
CFBridgingRelease(ptr);
to
CFRelease(ptr) .
__bridge_retained or CFBridgingRetain casts an Objective-C pointer to a Core Foundation pointer and also transfers ownership to you.
You are responsible for calling CFRelease or a related function to relinquish ownership of the object.
Taken from https://developer.apple.com/library/content/documentation/CoreFoundation/Conceptual/CFDesignConcepts/Articles/tollFreeBridgedTypes.html.
Related
The last attribute of glVertexAttribPointer is of type const GLvoid*. But is it really a pointer? It is actually an offset. If I put 0, it means an offset of 0 and not a null pointer to an offset. In my engine, I use this function:
void AbstractVertexData::vertexAttribPtr(int layout) const
{
glVertexAttribPointer(layout,
getShaderAttribs()[layout]->nbComponents,
static_cast<GLenum>(getShaderAttribs()[layout]->attribDataType),
getShaderAttribs()[layout]->shouldNormalize,
getVertexStride(layout),
reinterpret_cast<const void*>(getVertexAttribStart(layout)));
}
getVertexAttribStart returns an intptr_t. When I run drmemory, it says "uninitialized read" and I want to remove that warning. This warning comes from the reinterpret_cast. I can't static_cast to a const void* since my value isn't a pointer. What should I do to fix this warning?
Originally, back in OpenGL-1.1 when vertex arrays got introduces, functions like glVertexPointer, glTexCoordPointer and so on were accepting pointers into client address space. When shaders got introduced they came with arbitrary vertex attributes and the function glVertexAttribPointer follows the same semantics (this was in OpenGL-2.1).
The buffer objects API was then reusing existing functions, where you'd pass an integer for a pointer parameter.
OpenGL-3.3 core eventually made the use of buffer objects mandatory and ever since the glVertexAttribPointer functions being defines with a void* in their function signature are a sore spot; I've written in extent about it in https://stackoverflow.com/a/8284829/524368 (but make sure to read the rest of the answers as well).
Eventually new functions got introduced that allow for a more fine grained control over how vertex attributes are accessed, replacing glVertexAttribPointer, and those operate purely on offsets.
Isn't a unique_ptr essentially the same as a direct instance of the object? I mean, there are a few differences with dynamic inheritance, and performance, but is that all unique_ptr does?
Consider this code to see what I mean. Isn't this:
#include <iostream>
#include <memory>
using namespace std;
void print(int a) {
cout << a << "\n";
}
int main()
{
unique_ptr<int> a(new int);
print(*a);
return 0;
}
Almost exactly the same as this:
#include <iostream>
#include <memory>
using namespace std;
void print(int a) {
cout << a << "\n";
}
int main()
{
int a;
print(a);
return 0;
}
Or am I misunderstanding what unique_ptr should be used for?
In addition to cases mentioned by Chris Pitman, one more case you will want to use std::unique_ptr is if you instantiate sufficiently large objects, then it makes sense to do it in the heap, rather than on a stack. The stack size is not unlimited and sooner or later you might run into stack overflow. That is where std::unique_ptr would be useful.
The purpose of std::unique_ptr is to provide automatic and exception-safe deallocation of dynamically allocated memory (unlike a raw pointer that must be explicitly deleted in order to be freed and that is easy to inadvertently not get freed in the case of interleaved exceptions).
Your question, though, is more about the value of pointers in general than about std::unique_ptr specifically. For simple builtin types like int, there generally is very little reason to use a pointer rather than simply passing or storing the object by value. However, there are three cases where pointers are necessary or useful:
Representing a separate "not set" or "invalid" value.
Allowing modification.
Allowing for different polymorphic runtime types.
Invalid or not set
A pointer supports an additional nullptr value indicating that the pointer has not been set. For example, if you want to support all values of a given type (e.g. the entire range of integers) but also represent the notion that the user never input a value in the interface, that would be a case for using a std::unique_ptr<int>, because you could get whether the pointer is null or not as a way of indicating whether it was set (without having to throw away a valid value of integer just to use that specific value as an invalid, "sentinel" value denoting that it wasn't set).
Allowing modification
This can also be accomplished with references rather than pointers, but pointers are one way of doing this. If you use a regular value, then you are dealing with a copy of the original, and any modifications only affect that copy. If you use a pointer or a reference, you can make your modifications seen to the owner of the original instance. With a unique pointer, you can additionally be assured that no one else has a copy, so it is safe to modify without locking.
Polymorphic types
This can likewise be done with references, not just with pointers, but there are cases where due to semantics of ownership or allocation, you would want to use a pointer to do this... When it comes to user-defined types, it is possible to create a hierarchical "inheritance" relationship. If you want your code to operate on all variations of a given type, then you would need to use a pointer or reference to the base type. A common reason to use std::unique_ptr<> for something like this would be if the object is constructed through a factory where the class you are defining maintains ownership of the constructed object. For example:
class Airline {
public:
Airline(const AirplaneFactory& factory);
// ...
private:
// ...
void AddAirplaneToInventory();
// Can create many different type of airplanes, such as
// a Boeing747 or an Airbus320
const AirplaneFactory& airplane_factory_;
std::vector<std::unique_ptr<Airplane>> airplanes_;
};
// ...
void Airline::AddAirplaneToInventory() {
airplanes_.push_back(airplane_factory_.Create());
}
As you mentioned, virtual classes are one use case. Beyond that, here are two others:
Optional instances of objects. My class may delay instantiating an instance of the object. To do so, I need to use memory allocation but still want the benefits of RAII.
Integrating with C libraries or other libraries that love returning naked pointers. For example, OpenSSL returns pointers from many (poorly documented) methods, some of which you need to cleanup. Having a non-copyable pointer container is perfect for this case, since I can protect it as soon as it is returned.
A unique_ptr functions the same as a normal pointer except that you do not have to remember to free it (in fact it is simply a wrapper around a pointer). After you allocate the memory, you do not have to afterwards call delete on the pointer since the destructor on unique_ptr takes care of this for you.
Two things come to my mind:
You can use it as a generic exception-safe RAII wrapper. Any resource that has a "close" function can be wrapped with unique_ptr easily by using a custom deleter.
There are also times you might have to move a pointer around without knowing its lifetime explicitly. If the only constraint you know is uniqueness, then unique_ptr is an easy solution. You could almost always do manual memory management also in that case, but it is not automatically exception safe and you could forget to delete. Or the position you have to delete in your code could change. The unique_ptr solution could easily be more maintainable.
I have a C++ dll with the following method:
//C++ dll method (external)
GetServerInterface(ServerInterface* ppIF /*[OUT]*/)
{
//The method will set ppIF
}
//ServerInterface is defined as:
typedef void * ServerInterface;
To access the dll from a C# project, I created a C++/CLI project and declared a managed class as follows:
public ref class ComWrapperManager
{
//
//
ServerInterface _serverInterface;
void Connect();
//
//
}
I use the Connect() method to call GetServerInterface as shown below. The first call works, the second doesn't. Can someone explain why? I need to persist that pointer as a member variable in the managed class. Any better way to do this?
void Connect()
{
ServerInterface localServerInterface;
GetServerInterface(&localServerInterface); //THIS WORKS
GetServerInterface(&_serverInterface); //THIS DOESNT
//Error 1 error C2664: 'ServerInterface ' :
//cannot convert parameter 1 from //'cli::interior_ptr<Type>'
//to 'ServerInterface *'
}
You are passing a pointer to a member of a managed object. Such pointers are special, known as interior pointers. They are tracked by the garbage collector, it will modify the pointer value when the managed object is moved when the GC compacts the heap.
Problem is, you are passing that pointer to unmanaged code. The GC is not capable of modifying the copy of the pointer value that the native code is using. Now disaster strikes when another thread triggers a garbage collection, just when the native code is executing and dereferences the pointer. The object no longer exists at the original address. Very, very bad. And extremely hard to diagnose since it is so unlikely to happen.
The compiler can see you making this mistake. And complains with C2664.
The workaround is to pass a pointer that's stored in a memory location that's not going to get moved by the GC. Such a location is very easy to come by, a local variable qualifies. It is stored on the stack, it isn't going to be moved. So make it look like this instead:
void Connect()
{
ServerInterface temp;
GetServerInterface(&temp);
this->_serverInterface = temp;
// etc..
}
Which you already discovered yourself, just don't forget to assign the class member.
Here's why you can't do the second one: _serverInterface is a void pointer that is part of a managed class. Think about what the garbage collector does... It's allowed to move the managed objects around in memory however it wants, so the address of the void pointer can change from moment to moment. Therefore, it's not valid to use that address.
There are two solutions to this:
As you noted, where you can pass the address of a stack variable to the unmanaged method. Unlike managed objects, the stack doesn't move when the garbage collector does its thing, so the address doesn't change. You can then take the data stored in the stack variable and copy it to the class field, and that works fine, because you're not dealing with the address of it.
As the other answerer noted, you can lock your managed object in memory. Once it can't move, you can take the address of the void pointer field without issue. (He's showing C# syntax where you're looking for C++/CLI syntax. I'm not at a compiler to check, but I believe that the C++/CLI syntax is not the same.)
Of the two solutions, I prefer #1, the one you already have implemented: Solution #2 introduces a block of unmovable memory in the middle of the space that the garbage collector wants to rearrange. Given a choice, I prefer not to hamstring the garbage collector.
If you capture a strong reference to self under ARC in an objective-C style block, you need to use a __weak pointer to avoid an ARC "retain cycle" problem.
// Right way:
- (void)configureBlock {
XYZBlockKeeper * __weak weakSelf = self;
self.block = ^{
[weakSelf doSomething]; // capture the weak reference
// to avoid the reference cycle
}
}
I really don't know what a retain cycle is, but this answer describes it a bit. I just know you should use a __weak pointer for Objective-C style blocks. See Avoid Strong Reference Cycles when Capturing self.
But my question is, do I need to create a weak pointer when capturing self under a C++ <functional> block?
- (void)configureBlock {
self.block = [self](){
[self doSomething]; // is this ok? It's not an objective C block.
}
}
C++ lambdas can captured variables either by value or by reference (you choose when you declare the lambda how to capture each variable).
Capturing by reference is not interesting, because references to local variables become invalid after you leave the variable's scope anyway, so there is no memory management issues at all.
Capturing by value: if the captured variable is an Objective-C object pointer type, then it gets interesting. If you are using MRC, nothing happens. If you are using ARC, then yes, the lambda "retains" captured variables of object pointer type, as long as they are __strong (not __weak or __unsafe_unretained). So, yes, it would create a retain cycle.
I'm trying to use QtConcurrent::map to run this function
//This function is used through QtConcurrent::map to create images from a QString path
void MainWindow::createQImage(QString* path) {
//create an image from the given path
QImage* t = new QImage(*path);
imageList->append(t);
}
on this container/sequence (declared in the mainwindow header and initialized in the mainwindow constructor)
QList<QImage *> *imageList = new QList<QImage *>;
Here's the code I'm trying to run
QFutureWatcher<void> futureWatcher;
futureWatcher.setFuture(QtConcurrent::map(imageList, &MainWindow::createQImage));
and here are the errors I'm getting:
request for member 'begin' in 'sequence', which is of non-class type 'QList<QImage*>*'
request for member 'end' in 'sequence', which is of non-class type 'QList<QImage*>*'
I need the "createQImage" function to be run for every element in "imageList," which can reach into the thousands. I believe the problem to be with the first parameter to the map function. And from what I've read, it may have to do with compatibility. There isn't much sample code online that I was able to relate to. I'm new to Qt and not the most experienced of programmers but I'd appreciate some help and feedback.
Alternatively, is there better way to do this using QtConcurrent?
Thanks in advance!
QtConcurrent::map wants a sequence as its first argument. You passed it a pointer to a sequence.
If you do
futureWatcher.setFuture(QtConcurrent::map(*imageList, &MainWindow::createQImage));
it should be happy.
Note that the compiler was reasonably clear about what the problem was. Take the time to read the errors carefully, they're usually not as cryptic as they perhaps at first seem. In this case it was telling you that the argument you passed was not of a class type. A quick look at the argument type at the end of the error reveals that it is a pointer.
QList, QImage, QString are Copy-On-Write types (see other Qt implicitly shared types), so you shouldn't use pointers to these types because they are basically already smart pointers.
And if you remove all pointers from your code, it should also fix the main problem.