I have got an exception throw :0x74AC4192 in main.exe: Microsoft C++ exception: std::bad_weak_ptr at memory location 0x001AF0D0.
in
Gasstation::Gasstation(int n,int m)
{
for (int i = 0; i < n; ++i)
{
pumps_.push_back(std::make_shared<Pumplace>());
}
cashregisters_ = std::make_shared<Cashregister> (shared_from_this(), m);
}
I also used this in the header :
class Gasstation : public std::enable_shared_from_this<Gasstation>
What could be the problem?
The issue with your code here, is that you are calling shared_from_this() within the constructor of the class itself, where strictly speaking, it has not been "made shared" yet. The constructor is called before a smart pointer to the object exists. To follow your example, if creating a shared_ptr to Gasstation:
std::shared_ptr<Gasstation> gasStation = std::make_shared<Gasstation>(5,10);
//gasStation is available as a smart pointer, only from this point forward
Its a limitation of enable_shared_from_this that shared_from_this cannot be called in a constructor.
One solution, though not as elegant, is to have a public method that sets the cashregisters_ variable. The method can be called after construction:
Gasstation::Gasstation(int n, int m)
{
for (int i = 0; i < n; ++i)
{
pumps_.push_back(std::make_shared<Pumplace>());
}
cashregisters_ = std::make_shared<Cashregsiter>(m);
}
Gasstation::initialise_cashregisters()
{
cashregisters_->set_gasstation(shared_from_this());
}
//driver code
std::shared_ptr<Gasstation> gasStation = std::make_shared<Gasstation>(5, 10);
gasStation->initialise_cashregisters();
This solution will require you to remember to call initialise_cashregisters every time you initialise Gasstation.
Short of that, your options are limited, and you may have to rethink your design. Have you considered using raw pointers-to-Gasstation in Cashregister instead of smart pointers? If cashregister_ is a private variable and will never exist beyond the lifetime of the Gasstation it is assigned to, using raw pointers may be a safe and elegant alternative.
Related
Note: Apologies if the title is unclear, I don't quite know how to express the issue in proper terms (improvement suggestions are very welcome).
Code, onlinegdb example of the working version and example of the non-working one first to simplify the explanation:
#include <iostream>
#include <vector>
#include <memory>
class A {
public:
int v = 0;
};
void some_library_function(const std::vector<A*>& objects)
{
// do something to each object without taking ownership
for(auto p : objects)
{
p->v = 42;
}
}
class B
{
public:
std::vector<std::shared_ptr<A>> m_objects; // this is a private field in my actual code
B():m_objects{std::make_shared<A>()}{};
void use_library()
{
std::vector<A*> observer_vector(m_objects.size());
for(int i=0; i<m_objects.size(); i++)
{
observer_vector[i] = m_objects[i].get(); // fails here if I use unique_ptr
}
some_library_function(observer_vector);
}
};
int main()
{
B b;
b.use_library();
std::cout << b.m_objects[0]->v;
return 0;
}
I have a library function that operates on a series of objects of class A passed in via std::vector<A*>. These objects are stored in a field of class B that owns the objects. I would like to model the "owns" part via a vector of std::vector<unique_ptr<A>>, but this makes it impossible to pass the objects down to the library function.
using shared_ptrs works, but I'm worried this is not as expressive as the unique_ptrs with regards to object ownership.
Is there a way to use unique_ptrs in the vector and still be able to use the library function?
You're already doing the right thing. A raw pointer is a perfectly reasonable way to model something with unknown or lacking ownership. You're not storing the vector anywhere, so there is no confusion and no risk.
The only problem here really is that you've had to regenerate the entire vector, which seems like a bit of a waste. Ultimately, if you're set on a vector<unique_ptr<A>> at the source, and you're stuck with vector<A*> at the destination, then there's nothing you can do about that. If the vector is small it doesn't really matter though.
observer_vector[i] = m_objects[i].get(); // fails if with unique_ptr because of operator= being deleted
No, that should be valid. You're just assigning a raw pointer.
I have two projects, one basic client and a dynamic library.
Here's what happens in the client:
int main()
{
Scrutinizer scru;
scru.Scrutinize();
return 0;
}
In the DLL, The Scrutinizer class is as such (__declspec(dllexport) and such omitted for Clarity)
Header
class ProcessesGenerator;
class Scrutinizer
{
public:
Scrutinizer();
~Scrutinizer();
ProcessesGenerator *ProcGenerator
void Scrutinize();
};
The forward declaration of ProcessesGenerator was 'mandatory' for me to avoid some kind of circular reference.
Constructor in .cpp file
Here is how I initialize it:
Scrutinizer::Scrutinizer()
{
ProcGenerator = &ProcessesGenerator();
}
More about this ProcessesGenerator class:
Header
class ProcessesGenerator
{
public:
ProcessesGenerator();
~ProcessesGenerator();
WinFinder winFinder;
std::vector<std::string> fooCollec;
void GenerateProcesses();
};
ProcessesGenerator.cpp
Constructor:
ProcessesGenerator::ProcessesGenerator()
{
//winFinder = WinFinder();//problem will be the same with or without this line
fooCollec = std::vector<std::string>{"one", "two", "three"};
}
A breakpoint in the constructor shows that the vector is initialized with the chosen values.
Problematic function:
void ProcessesGenerator::GenerateProcesses() {
std::string foo = "bar";
fooCollec = std::vector<std::string>{};//read access violation
fooCollec.push_back(foo);//read access violation
winFinder.SomeVector= std::vector<std::string>{};//read access violation
}
Once there, I Can see that the size of vector is reset to 0. Any attempt to re-initialize it, or to push an element results in read access violation .Same with the vecotr member of its WinFinder member. I guess the flaw is obvious, but I really don't get it,
Thanks!
Your problem is with
Scrutinizer::Scrutinizer()
{
ProcGenerator = &ProcessesGenerator();
}
What you are doing is taking the address of a temporary object. That object will be destroyed and the end of that line and you will be left with a pointer that doesn't point to a valid object.
The old way to fix it would be to use
Scrutinizer::Scrutinizer()
{
ProcGenerator = new ProcessesGenerator();
}
But now you have to implement the copy constructor, copy assignment operator, and the destructor. Since you have a modern compiler what you can do instead is make ProcGenerator a std:unique_ptr<ProcessesGenerator> and then Scrutinizer() becomes
Scrutinizer::Scrutinizer() : ProcGenerator(make_unique<ProcessesGenerator>()) {}
I would also like to add that &ProcessesGenerator(); should not even compile. Unfortunately MSVS has a non-standard extension that allows this to compile. You can turn on the /Za compiler option (enforce ANSI compatibility) and then you should get an error like
error C2102: '&' requires l-value
The line ProcGenerator = &ProcessesGenerator(); makes a temporary ProcessesGenerator, takes its address and then puts it in your ProcGenerator pointer. The temporary is then destroyed, leaving garbage.
You probably wanted to be allocating it on the heap ProcGenerator = new ProcessesGenerator; but even in that case I would strongly suggest using unique_ptr instead of a raw pointer.
Preface:
this question is closely related to these ones: ...
- C++: Avoiding Static Initialization Order Problems and Race Conditions Simultaneously
- How to detect where a block of memory was allocated?
... but they have NO positive solution and my actual target use-case is slightly different.
During construction of the object I need to know if it is initialized in static memory bock ( BSS) or is it instantiated in Heap.
The reasons are follow:
Object by itself is designed to be initialized to "all zeros" in constructor - therefore no initialization is needed if object is statically initialized - entire block with all objects is already set to zeros when program is loaded.
Static instances of the object can be used by other statically allocated objects and alter some member variables of the object
Order of initialization of static variables is not pre-determined - i.e. my target object can be invoked before its constructor is invoked, thus altering some of its data, and constructor can be invoked later according to some unknown order of initialization of statics thus clearing already altered data. That is why I'd like to disable code in constructor for statically allocated objects.
Note: in some scenarios Object is the subject for severe multi-threaded access (it has some InterlockedIncrement/Decrement logic), and it has to be completely initialized before any thread can touch it - what i can guaranteed if i explicitly allocate it in Heep, but not in static area (but i need it for static objects too).
Sample piece of code to illustrate the case:
struct MyObject
{
long counter;
MyObject() {
if( !isStaticallyAllocated() ) {
counter = 0;
}
}
void startSomething() { InterlockedIncrement(&counter); }
void endSomething() { InterlockedDecrement(&counter); }
};
At the moment I'm trying to check if 'this' pointer in some predefined range, but this does not work reliably.
LONG_PTR STATIC_START = 0x00400000;
LONG_PTR STATIC_END = 0x02000000;
bool isStatic = (((LONG_PTR)this >= STATIC_START) && (LONG_PTR)this < STATIC_END));
Update:
sample use-case where explicit new operator is not applicable. Code is 'pseudo code', just to illustrate the use-case.
struct SyncObject() {
long counter;
SyncObject() {
if( !isStaticallyAllocated() ) {
counter = 0;
} }
void enter() { while( counter > 0 ) sleep(); counter++; }
void leave() { counter--; }
}
template <class TEnum>
struct ConstWrapper {
SyncObject syncObj;
TEnum m_value;
operator TEnum() const { return m_value; }
LPCTSTR getName() {
syncObj.enter();
if( !initialized ) {
loadNames();
intialized = true;
}
syncObj.leave();
return names[m_value];
}
}
ConstWrapper<MyEnum> MyEnumValue1(MyEnum::Value1);
You can probably achieve this by overwriting the new operator for your class. In your customized new, you can set a "magic byte" within the allocated memory, which you can later check for. This will not permit distinguishing stack from heap, but statically from dynamically allocated objects, which might be sufficient. Note, however, that in the following case
class A {
};
class B {
A a;
};
//...
B* b = new B;
b.a will be considered statically allocated with the proposed method.
Edit: A cleaner, but more complicated solution is probably a further customization of new, where you can keep track of dynamically allocated memory blocks.
Second edit: If you just want to forbid static allocation, why don't you just make the constructor private and add a factory function to the class dynamically creating the object and delivering the pointer?
class A {
private:
A () { ... }
public:
static A* Create () { return new A; }
};
I think that the best way for you to control this is to create a factory for your class. That way you have complete control of how your objects are created instead of making complicated guesses over what memory is used.
The first answer is: not portably, and it may not be possible at all on
some platforms. Under Solaris (and I think Linux as well), there is an
implicitly defined global symbol end, comparison of arbitrary
addresses works, and if this < &end (after the appropriate
conversions), the variable is static, at least as long as no dynamic
loading is involved. But this is far from general. (And it definitely
fails anytime dynamic linking is involved, regardless of the platform.)
The solution I've used in the past was to make the distinction manually.
Basically, I designed the class so that the normal constructor did the
same thing as zero initialization, and I then provided a special no-op
constructor for use with static objects:
class MayBeStatic
{
public:
enum ForStatic { isStatic };
MayBeStatic() { /* equivalent of zero initialization */ };
MayBeStatic( ForStatic ) { /* do absolutely nothing! */ };
// ...
};
When defining an instance with static lifetime, you use the second
constructor:
MayBeStatic object( MayBeStatic::isStatic );
I don't think that this is guaranteed by the standard; I think the
implementation is allowed to modify the memory any way it wants before
invoking the constructor, and in particular, I think it is allowed to
"redo" the zero initialization immediately before invoking the
constructor. None do, however, so you're probably safe in practice.
Alternatively, you can wrap all static instances in a function, so that
they are local statics, and will be initialized the first time the
function is called:
MayBeStatic&
getStaticInstance()
{
static MayBeStatic theInstance;
return theInstance;
}
Of course, you'll need a separate function for each static instance.
It looks like after thinking for a while, I've found a workable solution to identify if block is in static area or not. Let me know, please, if there are potential pitfalls.
Designed for MS Windows, which is my target platform - by another OS I actually meant another version of MS Windows: XP -> Win7. The idea is to get address space of the loaded module (.exe or .dll) and check if block is within this address space. Code which calculates start/end of static area is put into 'lib' segment thus it should be executed before all other static objects from 'user' segment, i.e. constructor can assume that staticStart/End variables are already initialized.
#include <psapi.h>
#pragma warning(push)
#pragma warning(disable: 4073)
#pragma init_seg(compiler)
#pragma warning(pop)
HANDLE gDllHandle = (HANDLE)-1;
LONG_PTR staticStart = 0;
LONG_PTR staticEnd = 0;
struct StaticAreaLocator {
StaticAreaLocator() {
if( gDllHandle == (HANDLE)-1 )
gDllHandle = GetModuleHandle(NULL);
MODULEINFO mi;
GetModuleInformation(GetCurrentProcess(), (HMODULE)gDllHandle, &mi, sizeof(mi));
staticStart = (LONG_PTR)mi.lpBaseOfDll;
staticEnd = (LONG_PTR)mi.lpBaseOfDll + mi.SizeOfImage;
// ASSERT will fail in DLL code if gDllHandle not initialized properly
LONG_PTR current_address;
#if _WIN64
ASSERT(FALSE) // to be adopted later
#else
__asm {
call _here
_here: pop eax ; eax now holds the [EIP]
mov [current_address], eax
}
#endif
ASSERT((staticStart <= current_address) && (current_address < staticEnd));
atexit(cleanup);
}
static void cleanup();
};
StaticAreaLocator* staticAreaLocator = new StaticAreaLocator();
void StaticAreaLocator::cleanup() {
delete staticAreaLocator;
staticAreaLocator = NULL;
}
So this is the situation.
I have a class
Class L_FullQuote
{
private:
vector<int> time;
..
}
and
Class B
{
L_FullQuote *Symbols[100];
void handle message()
}
Inside handle msg
i have this statement
Symbols[i]->time.push_back(2);
the code builds fine..but when i use the generated dll. the application just crashes..sometimes it takes me to a nxt poiner error in vector..but mostly the whole application just crashes.
It works fine without that line.
Please help
Thanks
You're already using vector, so why not take it one step further? Using std::vector will allow you to focus on writing your functionality, rather than worrying about memory management.
This example differs slightly from what you originally posted. Your original question class B has an array of 100 pointers that each must be initialized. In the example below, we create a std::vector of L_FullQuote objects that is initially sized to 100 objects in the constructor.
class L_FullQuote
{
public:
vector<int> time;
};
class B
{
public:
// Initialize Symbols with 100 L_FullQuote objects
B() : Symbols(100)
{
}
std::vector<L_FullQuote> Symbols;
void handle_message()
{
Symbols[i].time.push_back(2);
// other stuff...
}
};
L_FullQuote *Symbols[100];
Here you declare an array of pointer to L_FullQuote, but you never initialize any of the pointers, so when you call:
Symbols[i]->...
You are dereferencing an invalid pointer. Also note that you have declared time as private (though your code wouldn't even compile this way, s B as a friend of A I assume?)
Simply declaring an array of pointers does not initialize each element to point to a valid object. You need to initialize each one, something like:
for(int i = 0; i < 100; ++i) {
Symbols[i] = new L_FullQuote();
}
Only then do you have an array full of valid pointers. Don't forget to deallocate them though!
time is private member of class L_FullQuote, from class B you don't have access to that field
I have the following structure:
struct CountCarrier
{
int *CurrCount;
};
And this is what I want to do:
int main()
{
CountCarrier carrier = CountCarrier();
*(carrier.CurrCount) = 2; // initialize the *(carrier.CurrCount) to 2
IncreaseCount(&carrier); // should increase the *(carrier.CurrCount) to 3
}
void IncreaseCount(CountCarrier *countCarrier)
{
int *currCounts = countCarrier->CurrCount;
(*currCounts)++;
}
So, my intention is specified in the comments.
However, I couldn't get this to work. For starters, the program throws an exception at this line:
*(carrier.CurrCount) = 2;
And I suspect the following line won't work as well. Anything I did wrong?
struct CountCarrier
{
int *CurrCount; //No memory assigned
};
You need to allocate some valid memory to the pointer inside the structure to be able to put data in this.
Unless you do so, What you ar trying to do is attempting to write at some invalid address, which results in an Undefined Behavior, which luckiy in this case shows up as an exception.
Resolution:
struct CountCarrier
{
int *CurrCount; //No memory assigned
CountCarrier():CurrCount(new(int))
{
}
};
Suggestion:
Stay away from dynamic allocations as long as you can.
When you think of using pointers always think whether you really need one. In this case it doesn't really seem that you need one, A simple int member would be just fine.
You need to create the pointer. ie. carrier->CurrCount = new int;
*(carrier.CurrCount)
This is dereferencing the pointer carrier.CurrCount, but you never initialized it. I suspect this is what you want:
carrier.CurrCount = new int(2);
I seriously doubt that your program throws an exception at the line:
*(carrier.CurrCount) = 2;
While throwing an exception is certainly allowed behaviour, it seems much more likely that you encountered an access violation that caused the process to be killed by the operating system.
The problem is that you are using a pointer, but your pointer is not initialised to point at anything. This means that the result of the pointer dereference is undefined.
In this situation there does not seem to be any advantage to using a pointer at all. Your CurrCount member would work just as well if it was just a plain int.
If you are using C++, then you should encash its facilities. Instead of correcting your code, I am showing here that how the code should look like:
struct CountCarrier
{
int CurrCount; // simple data member
CountCarrier(int count) : CurrCount(count) {} // constructor
CountCarrier& operator ++ () // overloaded operator
{
++ CurrCount;
return *this;
}
};
We are overloading operator ++, because you have only one data member. You can replace with some named method also, like void IncrementCount().
CountCarrier carrier(2);
++ carrier;
As Als said, you need to provide some memory for the code to work.
But why make it so complicated? You don't need any pointers for the code you have to work. The "modern C++" way looks more like this:
struct CountCarrier
{
public:
CountCarrier(int currCount) : currCount(currCount) {}
void IncreaseCount() { ++currCount; }
int GetCount() const { return currCount; }
private:
int currCount;
};
int main()
{
CountCarrier carrier(2); // Initialize carrier.currCount to 2
carrier.IncreaseCount(); // Increment carrier.currCount to 3
}
Note how much cleaner and less error prone that is. Like I said, pick up a good introductory C++ book and read through it.