inserting "this" into an STL map from the constructor - visual-c++

VERSION 1
class Doh {
private:
static std::map<const std::string, const Doh*> someMap;
std::string stringValue_;
public:
Doh(std::string str) : stringValue_(str) {
Doh::someMap.insert(
std::make_pair<const std::string,const Doh*>
(this->stringValue_,this)
);
}
}
The above was ok with MSVC 2010 but with MSVC 2008 it fails – and I guess it is because the object is not constructed yet when it is inserted in the map (I got a memory access violation).
So, I tried a delayed insertion, which worked:
VERSION 2
Doh(std::string str) : stringValue_(str) {
boost::thread(&Doh::insertIntoTheStaticMap,this);
}
void insertIntoTheStaticMap() {
boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
Doh::someMap.insert(
std::make_pair<const std::string,const Doh*>
(this->stringValue_,this)
);
}
But as you might be able to guess, my intention is to have the static Doh::someMap as a common lookup dictionary.
VERSION 1 didn’t need any thread-safety because I would create all Doh instances in the same thread – in initialization blocks - which would be called by dynamic initializers before I enter main().
But with VERSION 2, the naïve sleep() is neither graceful nor reliable (not to mention, I might need to lock the map before insertion).
What would be a nice KISS approach?

Only potential issue I see is the initialization of the static member, if there are multiple source files. Try guarding it with a function.
class Doh {
private:
static std::map< std::string, Doh * > &get_map() {
static std::map< std::string, Doh * > someMap;
return someMap; // initialize upon first use
}
std::string stringValue_;
public:
Doh(std::string str) : stringValue_(str) {
get_map().insert(
std::make_pair
(this->stringValue_,this)
);
}
};

In neither version is there any sign of init for stringvalue_ - what does the debugger show you about this key when you hit the map insert in version 1 of the code? How is this field set up, and what is its type?
Running this in the debugger for VS2008 should allow you to narrow down the point of failure into the <map> source, I would have thought.

Related

Visual C++ lambdas always output debug information

If I instantiate a lambda somewhere (and the compiler doesn't inline it), I can find a string showing where the lambda is located in my c++ code like this:
... ?AV<lambda_1>#?0??MyFunction#MyScopedClass#MyNamespace##SAXXZ# ...
I don't want this information in the executable, as it could give away important names of classes and functions.
All kinds of output debug information are turned off. If I use a normal function instead, the final executable doesn't have this information, so manually converting all lambdas into normal functions would "fix it". But what's the best way to handle this? Can we tell the compiler to transform lambdas into normal functions?
UPDATE: I tested with other compilers: g++ and clang. They both leave the same references. I also found another unanswered question about this Gcc - why are lambdas not stripped during release build Please don't come with the "why do you care about a few symbols anyway".
Here's some code you can test with:
#include <iostream>
#include <functional>
class MyUnscopedClass
{
public:
MyUnscopedClass(const std::function<void(int x)>& f) :
f(f)
{
}
std::function<void(int x)> f;
};
namespace MyNamespace
{
class MyScopedClass
{
public:
static void temp1(int x)
{
std::cout << x * (x + 1);
}
static void MyFunction()
{
//MyUnscopedClass obj(temp1); // no symbols
MyUnscopedClass obj([](int x) // ?AV<lambda_1>#?0??MyFunction#MyScopedClass#MyNamespace##SAXXZ#
{
std::cout << x;
});
obj.f(23);
}
};
}
int main()
{
MyNamespace::MyScopedClass::MyFunction();
}
With the help of #dxiv in the comments, I found the problematic setting.
Configuration Properties > General > C++ Language Standard
can't be, for some reason,
Preview - Features from the Latest C++ Working Draft (std:c++latest)
So I set it to the second most recent one
ISO C++17 Standard (std:c++17)
and I get a random identifier instead.
AV<lambda_f65614ace4683bbc78b79ad57f781b7f>##
I'm still curious how this identifier is chosen though.

Lambda expressions (C++0x) not working in C++/CLI? [duplicate]

One of the cool new C++ features in Visual Studio 2010 are lambda expressions. However, I can't get them to work within a managed class.
class UnmanagedClass {
void Foo() {
// Creating empty lambda within unmanaged class.
// This compiles fine.
auto lambda = [](){ ; };
}
};
ref class ManagedClass {
void Foo() {
// Creating empty lambda within managed class.
// This creates error C3809:
// A managed type cannot have any friend functions/classes/interfaces.
auto lambda = [](){ ; };
}
};
My best guess is that the compiler creates the anonymous function class as a friend class, even though I never use class members. This seems to mean that lambdas cannot be used at all within ref classes.
I was so happy when I read that VS2010 adds lambda expressions to C++. Does anybody know how to get them to work within ref classes?
Looks like it is being considered for future versions. Otherwise known as: "We'll get to it."

Why C++ CLI has no default argument on managed types?

The following line has the error Default argument is not allowed.
public ref class SPlayerObj{
private:
void k(int s = 0){ //ERROR
}
}
Why C++ has no default argument on managed types ?
I would like to know if there is a way to fix this.
It does have optional arguments, they just don't look the same way as the C++ syntax. Optional arguments are a language interop problem. It must be implemented by the language that makes the call, it generates the code that actually uses the default argument. Which is a tricky problem in a language that was designed to make interop easy, like C++/CLI, you of course don't know what language is going to make the call. Or if it even has syntax for optional arguments. The C# language didn't until version 4 for example.
And if the language does support it, how that compiler knows what the default value is. Notable is that VB.NET and C# v4 chose different strategies, VB.NET uses an attribute, C# uses a modopt.
You can use the [DefaultParameterValue] attribute in C++/CLI. But you shouldn't, the outcome is not predictable.
In addition to the precise answer from Hans Passant, the answer to the second part on how to fix this, you are able to use multiple methods with the same name to simulate the default argument case.
public ref class SPlayerObj {
private:
void k(int s){ // Do something useful...
}
void k() { // Call the other with a default value
k(0);
}
}
An alternative solution is to use the [OptionalAttribute] along side a Nullable<int> typed parameter. If the parameter is not specified by the caller it will be a nullptr.
void k([OptionalAttribute]Nullable<int>^ s)
{
if(s == nullptr)
{
// s was not provided
}
else if(s->HasValue)
{
// s was provided and has a value
int theValue = s->Value;
}
}
// call with no parameter
k();
// call with a parameter value
k(100);

Why the bad_alloc(const char*) was made private in Visual C++ 2012?

I am just trying to compile a bit bigger project using the Visual Studio 2012 Release Candidate, C++. The project was/is compiled using the VS2010 now. (I am just greedy to get the C++11 things, so I tried. :)
Apart of things that I can explain by myself, the project uses the code like this:
ostringstream ostr;
ostr << "The " __FUNCTION__ "() failed to malloc(" << i << ").";
throw bad_alloc(ostr.str().c_str());
The compiler now complains
error C2248: 'std::bad_alloc::bad_alloc' : cannot access private member declared
in class 'std::bad_alloc'
... which is true. That version of constructor is now private.
What was the reason to make that version of constructor private? Is it recommended by C++11 standard not to use that constructor with the argument?
(I can imagine that if allocation failed, it may cause more problems to try to construct anything new. However, it is only my guess.)
Thanks,
Petr
The C++11 Standard defines bad_alloc as such (18.6.2.1):
class bad_alloc : public exception {
public:
bad_alloc() noexcept;
bad_alloc(const bad_alloc&) noexcept;
bad_alloc& operator=(const bad_alloc&) noexcept;
virtual const char* what() const noexcept;
};
With no constructor that takes a string. A vendor providing such a constructor would make the code using it not portable, as other vendors are not obliged to provide it.
The C++03 standard defines a similar set of constructors, so VS didn't follow this part of the standard even before C++11. MS does try to make VS as standard compliant as possible, so they've probably just used the occasion (new VS, new standard) to fix an incompatibility.
Edit: Now that I've seen VS2012's code, it is also clear why the mentioned constructor is left private, instead of being completely removed: there seems to be only one use of that constructor, in the bad_array_new_length class. So bad_array_new_length is declared a friend in bad_alloc, and can therefore use that private constructor. This dependency could have been avoided if bad_array_new_length just stored the message in the pointer used by what(), but it's not a lot of code anyway.
If you are accustomed to passing a message when you throw a std::bad_alloc, a suitable technique is to define an internal class that derives from std::bad_alloc, and override ‘what’ to supply the appropriate message.
You can make the class public and call the assignment constructor directly, or make a helper function, such as throw_bad_alloc, which takes the parameters (and additional scalar information) and stores them in the internal class.
The message is not formatted until ‘what’ is called. In this way, stack unwinding may have freed some memory so the message can be formatted with the actual reason (memory exhaustion, bad request size, heap corruption, etc.) at the catch site. If formatting fails, simply assign and return a static message.
Trimmed example:
(Tip: The copy constructor can just assign _Message to nullptr, rather than copy the message since the message is formatted on demand. The move constructor, of course can just confiscate it :-).
class internal_bad_alloc: public std::bad_alloc
{
public:
// Default, copy and move constructors....
// Assignment constructor...
explicit internal_bad_alloc(int errno, size_t size, etc...) noexcept:
std::bad_alloc()
{
// Assign data members...
}
virtual ~internal_bad_alloc(void) noexcept
{
// Free _Message data member (if allocated).
}
// Override to format and return the reason:
virtual const char* what(void) const noexcept
{
if (_Message == nullptr)
{
// Format and assign _Message. Assign the default if the
// format fails...
}
return _Message;
}
private:
// Additional scalar data (error code, size, etc.) pass into the
// constructor and used when the message is formatted by 'what'...
mutable char* _Message;
static char _Default[];
}
};
//
// Throw helper(s)...
//
extern void throw_bad_alloc(int errno, size_t size, etc...)
{
throw internal_bad_alloc(errno, size, etc...);
}

System.Linq.Dynamic .Select("new ...") does not appear to be thread safe

I grabbed System.Linq.Dynamic.DynamicQueryable from here:
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
The issue that I am running into is in code that looks like this:
var results = dataContext.GetTable<MyClass>.Select("new (MyClassID, Name, Description)").Take(5);
It appears that if that line of code is executed by multiple threads near simultaneously, Microsoft's dynamic Linq code crashes in their ClassFactory.GetDynamicClass() method, which looks like this:
public Type GetDynamicClass(IEnumerable<DynamicProperty> properties)
{
rwLock.AcquireReaderLock(Timeout.Infinite);
try
{
Signature signature = new Signature(properties);
Type type;
if (!classes.TryGetValue(signature, out type))
{
type = CreateDynamicClass(signature.properties);
classes.Add(signature, type); // <-- crashes over here!
}
return type;
}
finally
{
rwLock.ReleaseReaderLock();
}
}
The crash is a simple dictionary error: "An item with the same key has already been added."
In Ms code, The rwLock variable is a ReadWriterLock class, but it does nothing to block multiple threads from getting inside classes.TryGetValue() if statement, so clearly, the Add will fail.
I can replicate this error pretty easily in any code that creates a two or more threads that try to execute the Select("new") statement.
Anyways, I'm wondering if anyone else has run into this issue, and if there are fixes or workarounds I can implement.
Thanks.
I did the following (requires .NET 4 or later to use System.Collections.Concurrent):
changed the classes field to a ConcurrentDictionary<Signature, Type> ,
removed all the ReaderWriterLock rwLock field and all the code referring to it,
updated GetDynamicClass to:
public Type GetDynamicClass(IEnumerable<DynamicProperty> properties) {
var signature = new Signature(properties);
return classes.GetOrAdd(signature, sig => CreateDynamicClass(sig.properties));
}
removed the classCount field and updated CreateDynamicClass to use classes.Count instead:
Type CreateDynamicClass(DynamicProperty[] properties) {
string typeName = "DynamicClass" + Guid.NewGuid().ToString("N");
...

Resources