Global variable gets different values when used in different static methods - c++

I have the following class that implements static methods that must use a single global array. It is defined as such:
//Defined in LockTrack.h file
enum LOCK_ID{
LOCKID_0,
LOCKID_1,
LOCKID_2,
LOCKID_COUNT
};
static LOCK_ID __glob_lock_ids[LOCKID_COUNT];
class CLockTrack
{
public:
static void getLockedLocks(/*parameters*/)
{
//__glob_lock_ids = points to 0x015ef558 address in memory
LOCK_ID lockID = __glob_lock_ids[0];
}
static void inline setLock(LOCK_ID lockID)
{
//__glob_lock_ids = points to 0x015ef330 address in memory
__glob_lock_ids[lockID] = LOCK_ON_FLAG;
}
};
But what happens is that the '__glob_lock_ids' pointer points to different memory locations in each method. Why? And how to fix this?

Nope, that's not a global. Change it to
extern LOCK_ID __glob_lock_ids[LOCKID_COUNT];
and move
LOCK_ID __glob_lock_ids[LOCKID_COUNT];
into a single implementation file. Your version, static, will effectively create a new variable for each translation unit that includes the header.

Related

How can I store values in my class private array? c++11

I have something that looks like this
class RestaurantCheck
{
private:
static const int MENU_LENGTH = 10;
static const string menu[MENU_LENGTH] = {"Gumbo", "Shrimp", etc...}
Right off the bat, I have a problem. I know I can't initialize the data in the array as it is now, so I tried this ...
class RestaurantCheck
{
private:
static const int MENU_LENGTH = 10;
static const string menu[MENU_LENGTH];
void displayMenu();
public:
void showMenu()
{
RestaurantCheck thisMenu;
thisMenu.displayMenu();
}
void RestaurantCheck::displaymenu()
{
menu[0] = "Shrimp"
menu[1] = "Gumbo"
etc...
cout << menu[0]
etc...
However I am unable to store data in the array like that as well.
How the heck am I supposed to store data in this array? As part of the assignment, the array must be a const static, it must be in private, and the displayMenu must also be private, called by a public function.
I hope what I'm getting at is clear, if not I'll try to provide more information.
EDIT:
I can not edit anything from the instructors source file. The source file is already created, and he will be using his own (provided) to test both my class file and my header file. Thus it needs to be initiated outside of sourcefile.
You are falling into the same trap as many before you. Your array is const, so it must be initialized when declared. But you can not initialize static string arrays in the class body. What do you do? You initialize it outside!
like this:
in your .h file:
static const std::string menu[10];
in your .cpp file:
const std::string RestaurantCheck::menu[10] = {"Shrimp", "Calamari", "Listeria"};
Is this what you are looking for?
You can initialize static non scalar members, but this must be done outside the class:
#include <string>
class RestaurantCheck{
static const int MENU_LENGTH = 3;
static const std::string menu[MENU_LENGTH];
};
const std::string RestaurantCheck::menu[RestaurantCheck::MENU_LENGTH] = {"Gumbo", "Shrimp", "Jar" };
note the "init line" must be present only in one file, best place is some .cpp file that is compiled to object. Here is what I mean:
restaurantcheck.h - RestaurantCheck header
restaurantcheck.cpp - RestaurantCheck implementation (best place for "init line")
main.cpp - program (where main() is located)

C++ static members, multiple Objects

I've got some trouble with static members and methods in C++.
This is the Class header:
class Decoration {
public:
//Static Methods
static void reloadList();
//Static Members
static std::unordered_map<int, Decoration> decorationMapID;
};
And in .cpp:
void Decoration::reloadList() {
sqlTable result = db->exec("SELECT id, name, description FROM decorations");
for(sqlRow r: result) {
Decoration::decorationMapID.insert(std::pair<int,Decoration>(atoi(r[0].c_str()), Decoration(r[1], r[2], atoi(r[0].c_str()))));
}
}
Now, in my mainWindow class (I'm using QT5), I call reloadList() and initialize the map.
The list is now filled in this Object.
In another Window-Class, I want to use this static list, but the list is empty. Could you explain how I have to use the static members to access the same list everywhere?
Declaration of second class:
in mainWindow.h:
ShoppingLists slDialog;
in mainWindow.cpp I call:
slDialog.setModal(true); slDialog.show();
Btw.: The whole thing is a CocktailDatabase, so my target is to have a List/Map for Cocktail-, Ingredient-, Decoration-, and Taste- Objects, which I can use without reloading it from SQLite.
1) The static member exists only once and is shared between all the instances of Decoration.
2) The question is why it is empty. Here some hints:
a) You think it is empty because some windows object was not refreshed and is not aware that your list was poupulated.
b) Your window get initiaslised before the static list is initialised
3) nevertheless an advice: don't make your static list public, especially if it has to be initialised before it's used. Use a public access function that makes sure it's initialised. Here the rough idea:
class Decoration {
public:
std::unordered_map<int, Decoration> getMap();
protected: // or even private ?
static void reloadList();
static bool loaded=false;
static std::unordered_map<int, Decoration> decorationMapID;
};
where getMap() would be something like:
if (!loaded) {
... // load the list here
loaded = true;
}
return (decorationMapID);
You are using the default-constructed value of the static variable before it had a chance to be populated. If you put breakpoints in the code that uses the value and the code that initializes it, you'll see that the latter is called after the former.

Avoid creating multiple copies of code in memory

I'm new to developing on embedded systems and am not used to having very little program memory (16kB in this case) to play with. I would like to be able to create global variables, arrays, and functions that I can access from anywhere in the program while only existing in one place in memory. My current approach is to use static class members and methods that I can use by simply including the header file (e.g. #include "spi.h").
What is the best approach for what I'm trying to do?
Here is an example class. From what I understand, variables such as _callback and function definitions like call() in the .cpp will only appear in spi.o so they will appear only once in memory, but I may be mixed up.
spi.h:
#ifndef SPI_H_
#define SPI_H_
#include "msp430g2553.h"
class SPI {
public:
typedef void (*voidCallback)(void);
static voidCallback _callback;
static char largeArray[1000];
static __interrupt void USCIA0TX_ISR();
static void call();
static void configure();
static void transmitByte(unsigned char byte, voidCallback callback);
};
#endif /* SPI_H_ */
spi.cpp:
#include "spi.h"
SPI::voidCallback SPI::_callback = 0;
char SPI::largeArray[] = /* data */ ;
void SPI::configure() {
UCA0MCTL = 0;
UCA0CTL1 &= ~UCSWRST;
IE2 |= UCA0TXIE;
}
void SPI::transmitByte(unsigned char byte, voidCallback callback) {
_callback = callback;
UCA0TXBUF = byte;
}
void SPI::call() {
SPI::_callback();
}
#pragma vector=USCIAB0TX_VECTOR
__interrupt void SPI::USCIA0TX_ISR()
{
volatile unsigned int i;
while (UCA0STAT & UCBUSY);
SPI::call();
}
The data members and the member functions of the class you wrote will only be defined once in memory. And if they're not marked static, the member functions will still only be defined once in memory. Non-static data members will be created in memory once for each object that you create, so if you only create one SPI object you only get one copy of its non-static data members. Short version: you're solving a non-problem.
As per Pete, static won't affect code doubling up, only member vars. In your example, there is 0 difference between static non static memory usage except perhaps for the _callback var (which you call out as an error.) And that one variable would only double up if the class were created more than once.
If you want code to not exist in memory when not in use, look into overlays or some sort of dynamic linking process. DLL type code will probably be major overkill for 16K, but overlays with compressed code might help you out.
Also, beware of extra linked in code from libraries. Closely examine your .map files for code bloat from innocuous function calls. For instance, a single printf() call will link in all sorts of vargs stuff if it is the only thing using it. Same for software floating point (if you don't have a FP unit by default.)

How can I initialize class variables in a header?

I'm writing a library where the user can define arbitrary structures and pass them to my library, which will then obtain the memory layout of the structure from a static member such structure must have as a convention.
For example:
struct CubeVertex {
// This is, per convention, required in each structure to describe itself
static const VertexElement Elements[];
float x, y, z;
float u, v;
};
const VertexElement CubeVertex::Elements[] = {
VertexElement("Position", VertexElementType::Float3),
VertexElement("TextureCoordinates", VertexElementType::Float2),
};
C++ best practices would suggest that I move the static variable and its initialization into my source (.cpp) file. I, however, want to keep the variable initialization as close to the structure as possible since whenever the structure changes, the variable has to be updated as well.
Is there a portable (= MSVC + GCC at least) way to declare such a variable inside the header file without causing ambiguous symbol / redefinition errors from the linker?
Consider a simple getter.
struct CubeVertex {
static const std::array<VertexElement, N>& GetElements() {
static const std::array<VertexElement, N> result = {
//..
};
return result;
}
//..
}
Immediate benefit: No array-to-pointer-decay.
What you could do here is using an anonymous namespace.
Wrap everything into "namespace { ... };" and you can then access CubeVertex::Elements like you normally do.
However, this creates a new instance of the static data everytime you include the headerfile, which adds to the executable's filesize.
It also has some limitations on how to use the class/struct, because you cannot call functions of that class from another file (which won't be a problem in this special case here).

Static variable definition order in c++

Hi i have a class tools which has static variable std::vector m_tools.
Can i insert the values into the static variable from Global scope of other classes defined in other files.
Example:
tools.h File
class Tools
{
public:
static std::vector<std::vector> m_tools;
void print()
{
for(int i=0 i< m_tools.size() ; i++)
std::cout<<"Tools initialized :"<< m_tools[i];
}
}
tools.cpp File
std::vector<std::vector> Tools::m_tools; //Definition
Using register class constructor for inserting the new string into static variable.
class Register
{
public:
Register(std::string str)
{
Tools::m_tools.pushback(str);
}
};
Different class which inserts the string to static variable in static variable
first_tool.cpp
//Global scope declare global register variable
Register a("first_tool");
////////
second_tool.cpp
//Global scope declare global register variable
Register a("second_tool");
Main.cpp
void main()
{
Tools abc;
abc.print();
}
Will this work?
In the above example on only one string is getting inserted in to the static list. Problem look like "in Global scope it tries to insert the element before the definition is done"
Please let me know is there any way to set the static definiton priority? Or is there any alternative way of doing the same.
You are likely, here, to encounter the issue referred to as Initialization Order Fiasco.
The problem is that the initialization order of globals (and static class variables are globals) is well-defined within a same translation unit (roughly, think .cpp) but is completely undefined across translation units. Therefore, there is no guarantee that the vector be initialized when you try to push items in there.
Your solution here ? Use local static variables:
class Tools
{
public:
static std::vector<std::string>& AccessTools()
{
static std::vector<std::string> Tools; // local static
return Tools;
}
private:
};
class Register
{
public:
Register(std::string str)
{
Tools::AccessTools().push_back(str);
}
};
It is guaranteed to be initialized upon first access... though it's not (and cannot be) thread safe; if you are in a multithreading situation, you need to call Tools::AccessTools in main before launching the other threads to guarantee the initialization.
The initialization order of static global variables in different compilation units is not defined in C++ - this is why you have a problem.
A workaround may be to call a static function which contains the first static variable as local. This way you can force it to be initialized before it is used:
// tools.h
class Tools
{
public:
static std::vector<std::vector>& getTools();
...
};
// tools.cpp
std::vector<std::vector>& Tools::getTools() {
static std::vector<std::vector> tools;
return tools;
}
...
class Register
{
public:
Register(std::string str)
{
Tools::getTools().pushback(str);
}
};
The initialization of statics is not specified by C++. C++ FAQ Lite call it the "static initialization order fiasco"
my2c