struct test_struct
{
test_struct() {}
~test_struct() {}
};
#include <vector>
#include <memory>
#include <cstdio>
int main()
{
printf("ctor begin\n");
{
std::vector<std::unique_ptr<test_struct>> test_vec;
const int count = 100000;
for (auto i = 0; i < count; i++) {
test_vec.emplace_back(new test_struct);
}
printf("dtor begin\n");
}
printf("dtor end\n");
}
I'm using VS2010, and found some ridiculous performance issue. The code above works well both in debug and release build (ctrl+f5), but when debugger is attached(f5), dtor call for unique_ptr class is intolerably slow. The result machine code is fairly optimized, so I don't expect that it's compiler issue rather than debugger's, but I don't know how to deal with it. My question is
Is this problem able to be reproduced on your machine?
What's the reason of this behaviour?
Is there any workaround?
The slowdown is caused by memory checking that occurs whenever memory is freed. However, this is a special system-/debugger-level heap, and isn't anything you can control from within your program.
There's a great article on the issue. To summarize: you have to set an environment variable to disable it!
Luckily, you can set project-specific environment variables from the Debugging options in the Project Settings for your project, so that the environment variable is only applied to your program.
I used this simplified program to test:
#include <iostream>
#include <memory>
#include <vector>
int main()
{
std::cout << "ctor begin" << std::endl;
{
std::vector<std::unique_ptr<int>> test_vec;
for (unsigned i = 0; i < 100000; i++)
test_vec.emplace_back(new int);
std::cout << "dtor begin" << std::endl;
}
std::cout << "dtor end" << std::endl;
}
By setting _NO_DEBUG_HEAP=1 as an environment variable (either system-wide, which I won't recommend, or through the Debugging options), the code runs in roughly the same amount of time irrespective of whether or not the debugger is attached.
Related
I have implemented my own wrapper around std::chrono::steady_clock and would like to prevent any other developer from using the original:
#include <iostream>
#include <chrono>
namespace my_chrono {
class MyClock : public std::chrono::steady_clock {
// stuff here...
};
}
int main()
{
auto my_now = my_chrono::MyClock::now(); // this should compile
auto chrono_now = std::chrono::steady_clock::now(); // this should be prevented
std::cout << my_now.time_since_epoch().count() << ", " << chrono_now.time_since_epoch().count() << std::endl;
return 0;
}
Unfortunately, I cannot find a way to force usage of MyClock over steady_clock (for example via compiler errors or warnings treated as errors).
You cannot make it impossible for some other code to be unable to use something you have no control over. And the C++ standard library is something over which you have no control.
#include <functional>
#include <map>
#include <string>
#include <iostream>
class X
{
public:
X()
{
std::cout << "Ctor\n";
}
private:
typedef std::map<std::string, std::function<void()>> ValidatorType;
const ValidatorType m_validators = ValidatorType
{
{
"some-string",
[]()
{
// validation code
std::cout << "Validating...\n";
}
}
};
};
int main()
{
std::cout << "Start...\n";
X x;
std::cout << "Complete...\n";
return 0;
}
The above code builds and runs successfully in debug and release mode on OS X using Xcode 7.2.1 and Clang 7.0.2.
It also builds and runs successfully in release mode on Windows 7 using Visual Studio Express 2013 for Windows Desktop.
However, it crashes when run in debug mode on Windows. An access violation occurs before the constructor finishes executing. The console output is as follows:
Start...
Ctor
If the initialisation of m_validators is moved to the constructor initialiser list then the error goes away.
Could this be a compiler bug or is there something wrong with the declaration?
I tried building your code with VS2015, and it runs fine in debug build. I got this output:
Start...
Ctor
Complete...
without any "crash".
It may be a compiler bug with VS2013. You may want to upgrade to a new C++ compiler.
As we know, using boehm-gc in multi-thread requires calling GC_register_my_thread with stack base from GC_get_stack_base. but It seems not to work well with C++11's thread library, such as std::thread... How can I use boehm-gc with C++11's thread library?
(I use VS2013)
edit: This is tested code. std::thread is good, but std::future doesn't work (stop on _CrtIsValidHeapPointer
#include <iostream>
#include <thread>
#include <future>
#define GC_THREADS
#include <gc.h>
#include <gc_cpp.h>
#pragma comment(lib, "gcmt-lib")
void foo()
{
GC_stack_base sb;
GC_get_stack_base(&sb);
GC_register_my_thread(&sb);
int *ptr;
for (int i = 0; i < 10; i++)
{
ptr = new (GC) int;
*ptr = 1;
}
GC_unregister_my_thread();
}
int main()
{
GC_INIT();
GC_allow_register_threads();
std::cout << "test for std::thread";
std::thread thrd(foo);
thrd.join();
std::cout << " [sucs]\n";
std::cout << "test for std::future";
std::future<void> fu = std::async(std::launch::async, foo);
fu.get();
std::cout << " [sucs]\n";
std::cin.get();
}
edit: here is a capture of stack trace (Sorry that it isn't English, but I think it doesn't matter, anyway)
and here is a debug message
HEAP[TestGC.exe]: Invalid address specified to RtlValidateHeap( 00E80000, 00C92F80 )
While debugging, I found The error occurs after fu.get().
edit: The error doesn't occur with /MD(or /MDd)...
(I think GC might touch library's pointers (namespcae Concurrency), but it is just guess;;)
Before you start using the collector and before you create the threads make sure that you issue both
GC_INIT, and
GC_allow_register_threads
Then in every thread follow it up with,
GC_get_stack_base/GC_register_my_thread, and eventually
GC_unregister_my_thread.
You didn't say what you are compiling with but it works for gcc 4.8 (with -std=c++11).
EDIT: The OP was able to resolve the issue by addressing the instruction above and compiling the code with the /MD[d] flags for the multi-threaded dynamic MSVCR100 runtime. The issue remained unresolved for the multithreaded statically compiled runtime.
This is really driving me crazy:
#include <iostream>
#include <vector>
#include <string.h>
#include <thread>
using namespace std;
void test() {
vector<string> myvector;
string a("Teststring");
myvector.push_back(a);
cout << myvector.begin()->length() << endl;
}
int main() {
thread(test).join();
return 0;
}
The code compiles fine with the -std=c++11 flag to the compiler and the -pthread flag to the linker.
BUT: Eclipse does either know the std::thread or the myvector.begin()->length(), even if the code runs fine eclipse warns me "Method 'length' could not be resolved".
I tried every possible solution in here: Eclipse CDT C++11/C++0x support without any success. This took me so many hours now, what am I doing wrong?!
Is there anybody getting a project setup without problems with this code?
EDIT: Other code example - same problem:
#include <iostream>
#include <vector>
#include <thread>
using namespace std;
class TestClass {
public:
void test() {
cout << "test" << endl;
}
};
void test() {
vector<TestClass> testClassVector;
TestClass x;
testClassVector.push_back(x);
testClassVector.begin()->test();
}
int main() {
thread(test).join();
return 0;
}
Compiles and runs correct, but returns in eclipse: Method 'test' could not be resolved
EDIT:
working versions:
((TestClass)*(testClassVector.begin())).test();
TestClass foo2 = *(testClassVector.begin());
foo2.test();
still not working:
testClassVector.begin()->test();
The last compiles and works like the two above, but eclipse still claims:
Method 'test' could not be resolved
Maybe I'm wrong, but I think your problem don't come from Eclypse. Juste, begin() on a vector return a std::vector<T>::iterator first, this is not a pointer and there is no method length, but you can ask for the vector size with myvector.size(); if this is what you want.
The problem could come from your #include <string.h> that is not the same as #include <string>, string.h is for string operation like strcmp, strstr, etc... juste string will define the std::string object.
I don't have Eclipse set up but the problem appears to be around std::string. Does the problem go away if you remove the threading from the example? (I also changed to #include <string> instead of string.h)
#include <iostream>
#include <vector>
#include <string>
#include <thread>
using namespace std;
#if 0
void test() {
vector<string> myvector;
string a("Teststring");
myvector.push_back(a);
cout << myvector.begin()->length() << endl;
}
#endif
int main() {
//thread(test).join();
vector<string> myvector;
string a("Teststring");
myvector.push_back(a);
cout << myvector.begin()->length() << endl;
return 0;
}
That should hopefully print out 10.
Update from comment:
Does this generate the Eclipse warning?
auto tmp = *(myvector.begin());
std::cout << tmp.length() << std::endl;
What about this?
std::string foo("abc123");
std::cout << foo.length() << std::endl;
I guess one more too:
std::string foo2 = *(myvector.begin());
std::cout << foo2.length() << std::endl;
The solution found:
I downloaded eclipse kepler Kepler
Created a new project and tried to compile this source code (like above):
#include <iostream>
#include <vector>
#include <thread>
using namespace std;
class TestClass {
public:
void test() {
cout << "test" << endl;
}
};
void test() {
vector<TestClass> testClassVector;
TestClass x;
testClassVector.push_back(x);
testClassVector.begin()->test();
}
int main() {
thread(test).join();
return 0;
}
On the first run eclipse told me, thread belongs to the new c++11 standard and I have to add -std=c++11 to the compiler flags. To use thread I also added -pthread to the linker flags. With this steps the code could be compiled, but eclipse marks the thread still as unknown. To fix this I proceeded the following step:
Under C/C++ Build (at project settings), find the Preprocessor Include Path and go to the Providers Tab. Deselect all except CDT GCC Builtin Compiler Settings. Then untag Share settings entries … . Add the option -std=c++11 to the text box called Command to get compiler specs.
Found here.
Now - unbelievable but true - it works, even without any errors marked by eclipse. The solution is using the (beta) version of eclipse, wich seems to handle this in a better way.
Thanks for all your help!
This code freezes VS2010 sp1:
// STC_14_1.cpp : Defines the entry point for the console application.
//
//#include "stdafx.h"
#include <exception>
#include <iostream>
#include <cstdlib>
using std::cerr;
using std::cout;
using std::cin;
void my_new_handler()
{
cerr << "Mem. alloc failed.";
std::exit(-1);
}
//std::unexpected_handler std::set_unexpected(std::unexpected_handler);
class STC
{
std::new_handler old;
public:
STC(std::new_handler n_h):old(std::set_new_handler(n_h))
{ }
~STC()
{
std::set_unexpected(old);
}
};
int main(int argc, char* argv[])
{
STC stc(&my_new_handler);
while (true)
{
auto tmp = new int[50000];
}
return 0;
}
Is it that I'm doing something wrong or it's VS's problem?
Your loop is endless:
while (true)
{
auto tmp = new int[50000];
}
You have to define a condition to exit outside of the loop. In counterpart, VS will be frozen iterating through the loop and draining memory from the heap (since you allocate a new block of memory in every iteration).
EDIT: Your handler is not called because it has to be defined as void __cdecl:
void __cdecl no_memory () {
cout << "Failed to allocate memory!\n";
exit (1);
}
Since handler is not called, the problem is in endless loop.
It works on my VS 2010.
When you say 'freezes', are you sure that it's not just that the code is still actually running and has not hit the new handler code yet. I tried running the example set_new_handler code from the MSDN here, and it still took a minute or so and the example is allocating 5000000 at a time rather than 50000.