Skip to content

Instantly share code, notes, and snippets.

@punmechanic
Created May 28, 2019 00:06
Show Gist options
  • Save punmechanic/a9569b49ab88b8595fb04815821dd401 to your computer and use it in GitHub Desktop.
Save punmechanic/a9569b49ab88b8595fb04815821dd401 to your computer and use it in GitHub Desktop.
// Is there any way I can avoid allocating new memory here? `bindings` lives for the lifetime of the application, so it's not going out of scope.
void register_type(lua_State* L, const char* type_name, const binding bindings[], int num_bindings) {
for (int i = 0; i < num_bindings; i++) {
binding b = bindings[i];
// This will go out of scope at the end of this function and is essentially akin to passing a null reference. It looks like this is because I am passing a reference to the local variable b rather than a reference to the array member bindings[i].
lua_pushlightuserdata(L, &b);
// Now, if I malloc this binding (which is shit), this will work just fine, because the memory will be allocated on the heap and stay live until after this function exits.
binding* shit_binding = malloc(sizeof(binding));
shit_binding->name = b.name;
shit_binding->method = b.method;
lua_pushlightuserdata(L, shit_binding);
// One way around this is to use pointer arithmetic, which seems hacky.
binding b = bindings[i];
lua_pushlightuserdata(L, bindings + i);
}
}
@punmechanic
Copy link
Author

punmechanic commented May 28, 2019

As it turns out, pointer arithmetic (or &bindings[i]) work fine, as long as I remove the const from bindings. This makes sense. My first clue should have been that I was able to to assign to b.name within the block - Given that bindings is meant to be constant, that would mean that, somewhere, I had removed the const-ness.

Since it's undefined behaviour to modify the array in place - bindings[0].name = "foo" (indeed, gcc will warn you about that), that must mean that I took a copy of the struct somewhere, which is what binding b = bindings[i]; was doing. This should have been my hint that I was not creating a pointer to bindings[i] but in fact to a local copy of the thing pointed to by bindings[i].

By passing a pointer directly to &bindings[i];, I am implicitly allowing the value pointed to by that pointer to be modified, which would be illegal with a const operator. Had I done this correctly, I would have noticed that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment