小编ama*_*ang的帖子

为什么boost :: mutex比vs2013的std :: mutex更快?

今天我写了一些代码来测试互斥锁的性能.

这是boost(1.54)版本,在vs2010上使用O2优化编译:

boost::mutex m;
auto start = boost::chrono::system_clock::now();
for (size_t i = 0; i < 50000000; ++i) {
    boost::lock_guard<boost::mutex> lock(m);
}
auto end = boost::chrono::system_clock::now();
boost::chrono::duration<double> elapsed_seconds = end - start;
std::cout << elapsed_seconds.count() << std::endl;
Run Code Online (Sandbox Code Playgroud)

这是在VS2013上编译的std版本,也有O2优化:

std::mutex m;
auto start = std::chrono::system_clock::now();
for (size_t i = 0; i < 50000000; ++i) {
    std::lock_guard<std::mutex> lock(m);
}
auto end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end - start;
std::cout << elapsed_seconds.count() << std::endl;
Run Code Online (Sandbox Code Playgroud)

有点不同但做同样的事情.我的CPU是Intel Core i7-2600K,我的操作系统是Windows 7 64bit,结果是:0.7020s vs 2.1684s,3.08倍.

boost :: …

c++ performance boost mutex c++11

11
推荐指数
1
解决办法
2811
查看次数

boost :: asio无法连接到没有WLAN的localhost

在我的计算机(Surface Pro 2)上,只有一个网络适配器,它是一个无线LAN适配器.

我参与了一个小型的C++项目,它使用boost :: asio连接到localhost并完成它的工作,一切都很好.

但今天我发现,如果我从互联网断开WLAN,这个程序不起作用.

boost :: asio的解析器会抛出异常:

tcp::resolver::query query("localhost", "10127");
tcp::resolver resolver(io_service_);
tcp::resolver::iterator iterator;

try {
    iterator = resolver.resolve(query);
}
catch (boost::system::system_error& e) {
    log(e.what());
}
Run Code Online (Sandbox Code Playgroud)

并且错误消息是:请求的名称有效,但未找到所请求类型的数据.

ping到localhost就可以了.

我感到困惑,本地网络程序是否需要互联网?本地网络程序是否需要LAN适配器?为什么ping工作正常?

c++ boost network-programming wlan boost-asio

8
推荐指数
2
解决办法
3205
查看次数

为什么数据断点在未对齐的地址上不起作用

在Visual Studio中调试C ++项目时,某些数据断点永远不会命中。

所以我写了一些测试代码:

#include <iostream>
#include <stdint.h>

void test(uint32_t* p)
{
    *p = 0;

    // set a data breakpoint on p

    *((char*)p + 2) = 0x1;

    std::cout << *p << std::endl;
}

uint32_t* alloc(size_t offset)
{
    char* p = new char[sizeof(uint32_t) + offset];
    p = p + offset;
    return (uint32_t*)p;
}

int main()
{
    test(alloc(0));    // test #1
    test(alloc(2));    // test #2
}
Run Code Online (Sandbox Code Playgroud)

如您所见,在功能测试中,* p的值将首先置零,然后将其隐式更改,我得到了一个小端CPU,因此必须为65536。

如果在p(4个字节)上设置数据断点以检测更改,则会得到两个不同的结果:是否命中。它取决于所指向的p的地址。

在我上面的测试代码中,测试#1将命中,而测试#2将不命中,#1和#2之间的区别是alloc(0)和alloc(2)返回的地址。

本文如何:在MSDN上设置数据断点不会讨论此问题。

数据断点不能在未对齐的地址上工作吗?

c++ debugging breakpoints visual-c++

5
推荐指数
1
解决办法
921
查看次数

在 LoadLibrary 上创建远程线程并取回 HMODULE

我最近在做 DLL 注入工作,所以我在谷歌上做了一些研究。现在我知道使用 CreateRemoteThread 是一个好方法。

ASLR(Address space layout randomization,因为Windows Vista)使得kernel32.dll的地址是随机的,但这并不影响整体,因为在一个会话中所有进程的kernel32.dll的基地址是一样的——直到操作系统重置。

所以这段代码通常可能是安全的:

void launchAndInject(const char* app, const char* dll)
{
    STARTUPINFOA si = {0};
    si.cb = sizeof(si);
    PROCESS_INFORMATION pi = {0};

    if (CreateProcessA(app, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi))
    {
        LPVOID loadLibrary = GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA");
        if (loadLibrary == NULL) {
            return;
        }
        SIZE_T len = ::strlen(dll) + 1;
        LPVOID addr = VirtualAllocEx(pi.hProcess, NULL, len, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
        if (addr == NULL) {
            return;
        }
        if (!WriteProcessMemory(pi.hProcess, addr, dll, len, …
Run Code Online (Sandbox Code Playgroud)

dll-injection

5
推荐指数
1
解决办法
3218
查看次数

将宏参数转换为字符串常量并考虑逗号

假设我有一个C宏定义的产品版本,如下所示:

#define FOO_VERSION 1,0,0,1
Run Code Online (Sandbox Code Playgroud)

我想在运行时打印它:

#define STRING_VALUE(x) #x

int main()
{
    std::cout << STRING_VALUE(FOO_VERSION) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

这将输出一个字符串"FOO_VERSION",而不是"1,0,0,1".宏参数'FOO_VERSION'未被替换.所以我再次尝试这样:

#define STRING_VALUE(x) STRING_VALUE__(x)
#define STRING_VALUE__(x) #x

int main()
{
    std::cout << STRING_VALUE(FOO_VERSION) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

它在Visual C++ 2013中有效.

这是一个跨平台的应用程序,尽管只有五行代码.当我使用clang编译代码时,会出现编译时错误:"为类似函数的宏调用提供的参数太多".我猜原因是'FOO_VERSION'中定义的逗号.所以第三个版本:

#define STRING_VALUE(x) STRING_VALUE__(x)
#define STRING_VALUE__(a, b, c, d) #a "," #b "," #c "," #d

int main()
{
    std::cout << STRING_VALUE(FOO_VERSION) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

这段代码在clang中工作,但是Visual C++会输出一个警告:"编译时宏'STRING_VALUE__'的实际参数不够",当然运行时输出不正确.

我的问题:是否定义了这种预处理器行为?我可以使用STRING_VALUE宏的通用版本吗?

c c++ macros

5
推荐指数
1
解决办法
256
查看次数

如何在Windows线程退出时的TLS插槽中释放对象?

例如,在多线程程序中:

struct TLSObject;

void foo()
{
    TLSObject* p = TlsGetValue(slot);
    if (p == 0) {
        p = new TLSObject;
        TlsSetValue(slot, p);
    }
    // doing something with p
}
Run Code Online (Sandbox Code Playgroud)

第一次在任何线程中调用foo()都会创建一个新的TLSObject。

我的问题是:如何删除TLSObject(如果我不使用boost :: thread和boost :: thread_specific_ptr)?

boost :: thread_specific_ptr可以在线程退出时执行清理工作,但是我想这取决于boost :: thread,不是针对普通的OS线程,而且它很慢。

c++ windows thread-local-storage

4
推荐指数
2
解决办法
1534
查看次数

std :: thread导致DLLMain中的死锁

所以,这就是我所说的:std很复杂.

在VS2013中,这个简单的程序会导致死锁.

#include <thread>
#include <windows.h>

void foo()
{
}

void initialize()
{
    std::thread t(foo);
}

BOOL APIENTRY DllMain(HMODULE, DWORD reason, LPVOID)
{
    switch (reason)
    {
    case DLL_PROCESS_ATTACH:
        initialize();
        break;
    case DLL_THREAD_ATTACH:
        break;
    case DLL_THREAD_DETACH:
        break;
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
Run Code Online (Sandbox Code Playgroud)

在DLLMain中创建一个线程是完全错误的?这不是真的.从Microsoft的"创建DLL的最佳实践"文档:" 如果不与其他线程同步,创建一个线程就可以工作 ".所以CreateThread工作,_beginthreadex工作,boost :: thread工作,但std :: thread不起作用.这是调用堆栈:

ntdll.dll!_NtWaitForSingleObject@12()
KernelBase.dll!_WaitForSingleObjectEx@12()
msvcr120d.dll!Concurrency::details::ExternalContextBase::Block() Line 151
msvcr120d.dll!Concurrency::Context::Block() Line 63
msvcr120d.dll!Concurrency::details::_Condition_variable::wait(Concurrency::critical_section & _Lck) Line 595
msvcp120d.dll!do_wait(_Cnd_internal_imp_t * * cond, _Mtx_internal_imp_t * * mtx, const xtime * target) Line 54
msvcp120d.dll!_Cnd_wait(_Cnd_internal_imp_t * * …
Run Code Online (Sandbox Code Playgroud)

c++ visual-c++ msvc12

4
推荐指数
1
解决办法
3186
查看次数

CRT初始化和DLLMain

行情:

从文档"创建DLL的最佳实践" http://download.microsoft.com/download/a/f/7/af7777e5-7dcd-4800-8a0a-b18336565f5b/DLL_bestprac.doc的Microsoft:

"DLL通常具有复杂的相互依赖性,隐式定义它们必须加载的顺序.库加载器有效地分析这些依赖关系,计算正确的加载顺序,并按顺序加载DLL." [1]

"(在DLLMain中)使用动态C运行时(CRT)中的内存管理功能.如果未初始化CRT DLL,调用这些函数可能会导致进程崩溃." [2]

来自MSDN:http://msdn.microsoft.com/en-us/library/988ye33t.aspx

"_DllMainCRTStartup函数执行多项操作,包括调用_CRT_INIT,它初始化C/C++运行时库并在静态非局部变量上调用C++构造函数.如果没有此函数,运行时库将保持未初始化状态".[3]

"除了初始化C运行时库之外,_DllMainCRTStartup还调用了一个名为DllMain的函数." [4]

问题:

如果您的DLL依赖于CRT DLL,基于[1],将首先加载CRT DLL(首先进行初始化),那么[2]如何发生?

基于[3][4],_DllMainCRTStartup将调用_CRT_INIT来初始化CRT,那么[2]会如何发生?

如果一个可执行文件通过"隐式链接"加载你的DLL,你的DLL的_DllMainCRTStartup(和DLLMain)将在可执行文件的入口点(mainCRTStartup或WinMainCRTStartup)之前被调用,基于 [3] - _DllMainCRTStartup调用_CRT_INIT初始化CRT和mainCRTStartup也将初始化CRT,那么CRT究竟发生了什么?

如果你的DLL将在mainCRTStartup之前加载,那么在DLLMain或其他导出函数中调用CRT函数是否安全?

谁会实际初始化CRT DLL?

dll crt msvcrt

3
推荐指数
1
解决办法
4594
查看次数

为什么 sleep_for 调用 FreeLibrary?

我很震惊地跟踪这个简单的代码:

#include <thread>

void foo()
{
    for (int i = 0; i < 1000000; ++i) {
        std::this_thread::sleep_for(std::chrono::nanoseconds(1));
    }
}

int main()
{
    std::thread t(foo);
    t.join();
}
Run Code Online (Sandbox Code Playgroud)

你猜怎么着 ?sleep_for 每次都调用 FreeLibrary !

kernel32.dll!_FreeLibraryStub@4()
msvcr120d.dll!Concurrency::details::DeleteAsyncTimerAndUnloadLibrary(_TP_TIMER * timer) Line 707
msvcr120d.dll!Concurrency::details::_Timer::_Stop() Line 111
msvcr120d.dll!Concurrency::details::_Timer::~_Timer() Line 100
msvcr120d.dll!`Concurrency::wait'::`7'::TimerObj::~TimerObj()
msvcr120d.dll!Concurrency::wait(unsigned int milliseconds) Line 155
test826.exe!std::this_thread::sleep_until(const xtime * _Abs_time) Line 137
test826.exe!std::this_thread::sleep_for<__int64,std::ratio<1,1000000000> >(const std::chrono::duration<__int64,std::ratio<1,1000000000> > & _Rel_time) Line 162
test826.exe!foo() Line 6
Run Code Online (Sandbox Code Playgroud)

为什么 sleep_for 必须调用 FreeLibrary ?

这个程序使用 boost 库需要 2 秒,使用 msvcrt(发布模式)需要 3 分钟以上(失去耐心)。我无法想象。

c++ visual-c++ msvc12

1
推荐指数
1
解决办法
380
查看次数