What's purpose of initializing a struct as a pointer? - go

Zap initializes its default option struct as follows in its grpc interceptor:
var (
defaultOptions = &options{
levelFunc: DefaultCodeToLevel,
shouldLog: grpc_logging.DefaultDeciderMethod,
codeFunc: grpc_logging.DefaultErrorToCode,
durationFunc: DefaultDurationToField,
messageFunc: DefaultMessageProducer,
timestampFormat: time.RFC3339,
}
)
And the later zap performs a copy of values:
*optCopy = *defaultOptions
What is the purpose of declaring the variable defaultOptions as a pointer and then later dereferencing it for copying? I was wondering if there is any issue with not using pointer:
defaultOptions = options{
levelFunc: DefaultCodeToLevel,
shouldLog: grpc_logging.DefaultDeciderMethod,
codeFunc: grpc_logging.DefaultErrorToCode,
durationFunc: DefaultDurationToField,
messageFunc: DefaultMessageProducer,
timestampFormat: time.RFC3339,
}
optCopy = &options{}
*optCopy = defaultOptions

A possible advantage with using a pointer is that you can then have that pointer set to nil; obviously if it is nil, you can't dereference it; but this might be used to indicate that there are no options and there may be code to handle this.
Caveat: I am not a Go programmer.

My guess, based on previous issues I had with big systems, is that with configuration structs, if for any reason some part of your software changes the value of something, that change will propagate to any function/member who has that pointer, and most of the times you don't want that to happen, you usually want that the configuration that you probably read from a file, stays the same, even if some function needs to do a transformation of a specific field of the struct holding that configuration.
So basically, you keep the original struct fresh, but you can send the pointer around to have its contents copied anywhere.
That's my educated guess, it is most likely an application architecture decision.
Edit: After further pondering:
If the author of the code had in his mind the idea of moving that data structure everywhere in his code, in multiple levels deep and broad, declaring it as value would mean he would have to copy it every time he wanted to move the data from function to function, or that the data structure could be erased by the end of execution of scope, whereas with a pointer he can move only the pointer around (much faster) and then only copy the data once the pointer arrives at the destination function.

Related

Why is my lambda capturing a pointer by value?

I have the following lambda
direction->addClickEventListener([=](Ref* sender){
std::unordered_map<int,int> data;
rep->getData(DIRECTION, data);
int last = data[1];
int rotation = (last + 45)%360;
LOG("l:%i r:%i",last,rotation);//Always logs l:0 r:45
direction->setRotation(rotation);
data[1] = rotation;
rep->setData(DIRECTION, data);
});
where getData is:
void getData(DATA_KEY key,std::unordered_map<int,int>& data){
//Modifies data with the appropriate values for key, for the current state of rep
}
void setData(DATA_KEY key,std::unordered_map<int,int>& data){
//Makes a copy of data stores it internally with key
}
rep is pointer, so I thought that whenever the lambda is called, the current value of data will always reflect the current state of rep. But it seems that it is always the value of whatever rep was at the time direction->addClickEventListener was called.
If I want to use the current state of rep, how ghouls I modify my lambda ?
EDIT: Since rep is a pointer, I can't can't capture by reference..
I'm not really sure what you're asking, so this might not be an answer to your problem, but it is an attempt to clarify what the problem with capturing by reference is.
It looks like you are having an event-based system. The important thing to know about events is that they can occur at any time.
Now lets say you have something like this (very simplified and pseudo-ish):
void some_function(some_type* rep)
{
add_event_listener([&]()
{
do_something(rep);
});
}
There is a very serious bug in the code above: When the event is invoked and the lambda is called, the function some_function will have returned, and therefore the scope of the local variable rep doesn't exist any more. So when rep is used in the lambda it is a reference to a variable that doesn't exist anymore (remember that rep is a local variable). That of course leads to undefined behavior.
If you capture by value instead, the pointer is copied meaning you now have two pointer variables, both pointing to the same memory. Then it doesn't matter if the first variable goes out of scope, because the second variable still is valid.
Pointer doesn't have state, methods or something. Pointer is abstract address of storage where your object is. "Reference" is synonymous to pointer in some ways, if you think in C terms, but they are different in C++ - you can pass pointer variable by reference, thus passing control over its value (not over the state of object it points to, that actually achieved by pointer). Pointer variable is also a storage, that contains value of pointer
You can pass any variable (storage) "by reference", which means that function can change value stored in that variable. In C that was done by passing pointers, but to pass pointer "by reference" they had to pass type like void** pointer to a pointer. In C++ & syntax is used to reduce the clutter.
[=] mans that all external variables are captured by value. This would allow anonymous function to read value of pointer, deference it and call methods\access fields of the objects it points to.
[&] would mean capture by reference. Pointer is variable. This would allow lamba to modify it, making it to point to other object.
If you do need only rep by reference use, [=. &rep].
How rep might be changed while lambda is running? If that happens in parallel thread, you'll probably need an atomic.
If you cannot change actual object your pointer refers to, that may mean that compiler does aliasing optimization because of illegal cast from one object to another, because casted away const modifier or low quality of implementation (that's rare) that causes aliasing optimization where it should not happen.

Does a `_` receiver on a value (non-pointer) still copy the value?

My question is whether or not a copy of a value is made when a method is invoked where _ is the receiver.
type Foo struct {
// Many fields, making a large struct
}
func (_ Foo) Test(v *T) int {
// Here we can't use the receiver but the method is still needed
}
So I'm wondering if Go implementations will still copy the Foo value when Test() is invoked, even though it's impossible to actually mutate the receiver value.
var f Foo
f.Test() // Is this making a copy?
I would also wonder about the case of a pointer, which is automatically dereferenced by default.
var f = new(Foo)
f.Test() // Is this making a copy?
I tried looking at the assembly, and I think it may be making the copy, but I just don't know enough to be sure.
For details on the situation:
This is an odd case where I can't use a pointer. The code is machine generated and required to cause a type to fulfill an interface while doing some initialization on the v parameter. (The generated code has metadata about the Foo that gets set on v.)
So if I make the receiver a pointer, the interface won't be fulfilled for "value" instances. This method will be invoked once for each instance, and instances can sometimes be large and/or created in great numbers, which is why I would like to avoid an unnecessary copy.
According to this blog post, the caller allocates stack elements for return values and the callee populates them.
This leads me to believe that the value is copied and then discarded.
That or a specialized callee would have to be generated in the case of _ receiver

En/Decode struct containing many interfaces with different implementations each with gob

I have a quite complex struct that contains many interfaces with each different implementations. For en/decoding that struct in gob I seem to have to register every implementation that could be possibly used for every interface. So I end up with a method along these lines:
func registerImplementations() {
gob.Register(&Type1{})
gob.Register(&Type2{})
gob.Register(&Type3{})
gob.Register(&Type4{})
....
}
which I need to call before en/decoding. Is there an easier way to do this? Or should I look into possibilities for generating this method, since it's quite tedious to keep track of all possible implementations?
The documentation says:
We must register the concrete type for the encoder and decoder (which would
normally be on a separate machine from the encoder). On each end, this tells the
engine which concrete type is being sent that implements the interface.
So, at some point, you're going to want to call gob.Register, but you do want your code to be maintainable. This leaves (broadly) two options:
Creating a function like you're doing now, calling each struct after one another.
Advantage: all your Register-calls in a list, so you'll easily spot if you miss one, and you surely won't register one twice.
Disadvantage: you'll have to update it when using another implementation. You'll also have to call this function some time before encoding/decoding.
Creating something like this:
func Register(i interface{}) error {
gob.Register(i)
return nil
}
And then when writing a new implementation in your (let's say) dummy package, you can put this line below / above the interface declaration.
var regResult = reg.Register(myNewInterface{})
This will be called on startup (because it's global).
Advantage: not having to update the registerImplementations method.
Disadvantage: you'll have your registers all across your code (which can consist of a lot of files) - so you might miss one.
As to which is better: I'll leave that up to you.

State of object after std::move construction

Is it legal/proper c++0x to leave an object moved for the purpose of move-construction in a state that can only be destroyed? For instance:
class move_constructible {...};
int main()
{
move_constructible x;
move_constructible y(std::move(x));
// From now on, x can only be destroyed. Any other method will result
// in a fatal error.
}
For the record, I'm trying to wrap in a c++ class a c struct with a pointer member which is always supposed to be pointing to some allocated memory area. All the c library API relies on this assumption. But this requirement prevents to write a truly cheap move constructor, since in order for x to remain a valid object after the move it will need its own allocated memory area. I've written the destructor in such a way that it will first check for NULL pointer before calling the corresponding cleanup function from the c API, so that at least the struct can be safely destroyed after the move.
Yes, the language allows this. In fact it was one of the purposes of move semantics. It is however your responsibility to ensure that no other methods get called and/or provide proper diagnostics. Note, usually you can also use at least the assignment operator to "revive" your variable, such as in the classical example of swapping two values.
See also this question

How can I stop execution in the Visual Studio Debugger when a private member variable changes value?

Let's say my class has a private integer variable called count.
I've already hit a breakpoint in my code. Now before I press continue, I want to make it so the debugger will stop anytime count gets a new value assigned to it.
Besides promoting count to a field and setting a breakpoint on the set method of the field, is there any other way to do this?
What you're looking for is not possible in managed code. In C++ this is known as data break point. It allows you to break whenever a block of memory is altered by the running program. But this is only available in pure native C++ code.
A short version of why this is not implemented is that it's much harder in managed code. Native code is nice and predictable. You create memory and it doesn't move around unless you create a new object (or explicitly copy memory).
Managed code is much more complex because it's a garbage collected language. The CLR commonly moves objects around in memory. Therefore simply watching a bit of memory is not good enough. It requires GC interaction.
This is just one of the issues with implementing managed break points.
I assume you're trying to do this because you want to see where the change in value came from. You already stated the way I've always done it: create a property, and break on the set accessor (except that you must then always use that set accessor for this to work).
Basically, I'd say that since a private field is only storage you can't break on it because the private field isn't a breakable instruction.
The only way I can think do do this, is to right click on the variable, and select "Find all references". Once it finds all the references, you can create a new breakpoint at each point in the code where the variable is assigned a value. This would probable work pretty well, unless you were passing the variable in by reference to another function and changing the value in there. In that case, you'd need some way of watching a specific point in memory to see when it changed. I'm not sure if such a tool exists in VS.
Like ChrisW commented. You can set a 'Data Breakpoint' but only for native (non-managed) code. The garbage collector will move allocated memory blocks around when the garbage collector runs. Thus, data breakpoints are not possible for managed code.
Otherwise, no. You must encapsulate access to your item for which you want to 'break on modify'. Since its a private member already, I suggest following Kibbee's suggestion of setting breakpoints wherever its used.
Besides promoting count to a field and setting a breakpoint on the set method of the field, is there any other way to do this?
Make it a property of a different class, create an instance of the class, and set a breakpoint on the property.
Instead of ...
test()
{
int i = 3;
...etc...
i = 4;
}
... have ...
class Int
{
int m;
internal Int(int i) { m = i; }
internal val { set { m = value; } get { return m; } }
}
test()
{
Int i = new Int(3);
...etc...
i.val = 4;
}
The thing is that, using C#, the actual memory location of everything is being moved continually: and therefore the debugger can't easily use the CPU's 'break on memory access' debugging register, and it's easier for the debugger to, instead, implement a code-location breakpoint.

Resources