2

Recently had some issues with static pointer. The code is part of a bigger project but esentially biols down to something like:

Class CustomClass {
   public:
   unsigned int SomeVar = 0;
};

....


namespace NS {
   inline static CustomClass* CustomPtr = nullptr;
}


// Initialise the CustomPtr when app starting
...
if (NS::CustomPtr != nullptr) {
   delete NS::CustomPtr;
   NS::CustomPtr = nullptr;
}

NS::CustomPtr = new CustomClass();


...

//Use the CustomPtr
// Note the Usage always comes after the initialisation
NS::CustomPtr->SomeVar = 10;   // <-- Throw read violation

There is a global namespace and that holds ppointer. When app start all pointer initialised on the heap (new) and ment to be available for the whole duration for the app. When new called, constructor executes and object saved in memory just fine, but the code result in a read violation when attempting to access any property of the CustomClass. Stepping in with the debugger turns out that the pointer is fine and can see it with its properties in the Debugger "Watch" part up until the line of code executes that dereferencing the pointer. On that line it changes to <struct in NULL> and becomes a null pointer.

The sulotion was to remove the "inline static" part. Now works fine. The question is why the "inline static" part broke everything?

Pain67
  • 326
  • 1
  • 9
  • was the `inline static` declaration in the header or in the `.cpp` file? – The Wrecker Mar 25 '23 at 11:33
  • In the header file. It is only one header file without a cpp. – Pain67 Mar 25 '23 at 12:00
  • 1
    What is you understanding of what `inline static` means? Why did you think you needed it in the first place? – Sam Varshavchik Mar 25 '23 at 12:07
  • Is all the code in the same file? Is it possible that we were using the pointer in a translation unit where the pointer was actually not initialized? – Riccardo Petraglia Mar 25 '23 at 12:56
  • possible dupe: [inline vs inline-static](https://stackoverflow.com/questions/50515591/c17-inline-variable-vs-inline-static-variable) – apple apple Mar 25 '23 at 13:40
  • @SamVarshavchik - the idea is to have it as static so there is only once instace. The reason for inline is (I might be wrong here) but when define static var in header in order to be able to assign value need to be inline (unless its a const value). – Pain67 Mar 25 '23 at 13:49
  • @RiccardoPetraglia - There is a separate header file with the namespace definiton and thers is multiple cpp files using the header. It must be initialise as the line above the attempted use can still see the values (based on VS debbuger watch). only on the actual line it turn into null. – Pain67 Mar 25 '23 at 13:49
  • Based on the comment from @appleapple, seems like i had a misunderstanding what "inline" means and do in a namespace scope. From the post linked it seems that it is pretty much pointless and do nothing int the above coce. But still leaves the questin why makeing that pointer static breaks it? – Pain67 Mar 25 '23 at 13:53
  • 1
    No, it looks like you misunderstand what `inline static` is, both on the `inline` and `static` part. In C++, unfortunately, `static` has several purposes. There are different kinds of `static` objects, that serve different purposes. Here, this results in different objects, in different translation units, that have the same name. But they are different objects, and there is no "only one instance". – Sam Varshavchik Mar 25 '23 at 13:53
  • The idea is that in this context `static` will create a copy of the pointer in each different translation unit. You must re-initialize it in each cpp file or you should initialize it in the header. I suppose the fact that it is valid until you reach the line where it is used does not mean much.. it is just about the way the implementation works. It actually expected that it points to null (because this is the way you initialize it in the header). If you want a global pointer across all the code, remove the `static`. – Riccardo Petraglia Mar 25 '23 at 13:56
  • @SamVarshavchik - My bad, by one instance i menat to have all cpp access the same object pointed to by the Ptr. Looking it now, not even sure why i was makeing them static in the first place. – Pain67 Mar 25 '23 at 13:58
  • @RiccardoPetraglia - Yes removing the static solves the issue. I was not awere that static means to create a copy for each unit (if used in namespace scope). – Pain67 Mar 25 '23 at 14:00
  • @RiccardoPetraglia - Can you post that as an answer so i can accept it as it seems like that is the issue. Was not aware that static used in this way is intended to create a separate copy for each unit where its used. – Pain67 Mar 25 '23 at 14:10

1 Answers1

0

static works differently depending on where it used. If using in namespace scope (global :: is a ns scope) it makes all translation units to have their own "copy" of the variable. In this case when NS::CustomPtr was assigned in one translation unit, it only affected that one unit. In all other translation unit, the variable is equal to NULL because this is the initialisation value the variable gets in the header.

From cppreference.com/Storage class specifiers

The static specifier is only allowed in the declarations of objects (except in function parameter lists), declarations of functions (except at block scope), and declarations of anonymous unions. When used in a declaration of a class member, it declares a static member. When used in a declaration of an object, it specifies static storage duration (except if accompanied by thread_local). When used in a declaration at namespace scope, it specifies internal linkage.

Riccardo Petraglia
  • 1,943
  • 1
  • 13
  • 25