2017-10-04 29 views
-1

我添加了一个新的类到解决方案的一部分的DLL。所有工作正常,直到我开始在this问题中讨论错误时,我将用调试器启动解决方案。这意味着调试器遇到了一些不好的情况,可能会造成腐败,尽管它没有明确指出它在哪里。可能未定义的行为,但为什么?

我的问题缩小到我添加的类,如果我删除它,解决调试正常,没有错误。但显然,我添加的课程没有任何问题!

所以我评论我的课,并添加一个新的简单(虚拟)Book类只是为了看它是否会产生同样的错误,但它不!然后,我将它看起来类似于我添加的类(从ofstream派生),仍然可以很好地调试,没有错误。

我评论它,并注释去掉,我原来的班,当我调试它再次出现错误!我剔除了这个类,现在只剩下构造函数/析构函数,我可以调试它,错误也会消失。我带回删除代码(使用撤消,以便精确恢复),并且这次它可以工作(当它不在之前),并且将调试罚款而不会抛出该腐败错误!

所以这听起来很像不确定的行为,但是这是一个被实例化也是正确的一个非常轻量级的独立的类是不确定的行为还是犯罪嫌疑人?如果是这样,为什么会在这种情况下导致这种行为?

以下是参考

class lfstream : public std::ofstream 
{ 
public: 
    lfstream(); 
    ~lfstream(); 

    void log(const std::string &text, int threadID); 
}; 

#ifdef _LOGDLL 
    #define API __declspec(dllexport) 
#else 
    #define API __declspec(dllimport) 
#endif 

API extern lfstream logstream; 

/* 
class Book : public std::ofstream 
{ 
public: 
    Book(); 
    ~Book(); 
    int WordCount(); 
}; 

API extern Book book; 
*/ 

.cpp文件

static char logfname[] = "debug.txt"; 

lfstream::lfstream(): std::ofstream(logfname) 
{ 
} 

lfstream::~lfstream() 
{ 
} 

void lfstream::log(const std::string &text, int threadID) 
{ 
    const time_t ctt = time(0); 
    *this << std::setw(40) << std::left << text << " thread id = " << threadID << "\t" << asctime(localtime(&ctt)); // << std::endl; 
} 

lfstream logstream; 

/* 
Book::Book() : std::ofstream("crash.txt") 
{ 
} 
Book::~Book() 
{ 
} 

int Book::WordCount() 
{ 
    return 50; 
} 

Book book; 
*/ 
+1

那么什么错误并线造成的呢?你的代码还有几个问题:1)全局变量2)试图从不同线程写入日志('threadID'是有原因的,对吗?)没有适当的同步3)尝试从不同线程使用'localtime'也可能让你陷入困境。另外给出的代码片段远离[mcve](https://stackoverflow.com/help/mcve) – VTT

+0

@VTT这是一个崩溃的对话框,它说'windows已经触发了应用程序中的断点。 exe'。它并没有说明发生了什么,并且在加载可执行文件的早期阶段发生了这种情况。我在OP中链接了一篇与之相关的帖子。 – zar

+0

“windows已触发了Apple.exe中的断点” - 这可能意味着您有一个触发断点的实际函数(如x86系统上的asm {int $ 3})。 – sehe

回答

2

你的代码显示了你期望在不同的线程被称为我的.h和.cpp文件。

无处的代码做的,我们看到的线程同步或临界区。

您需要使用的关键部分,以防止种族条件。竞赛条件是Undefined Behaviour

最常见的标准C++解决方案是使用std::mutexstd::lock_guard来确保单个线程可以位于(a)代码的关键部分。

采样/主意:

#include <mutex> 
// .... 


static std::mutex s_log_mutex; 

void lfstream::log(const std::string &text, int threadID) 
{ 
    std::lock_guard<std::mutex> lock(s_log_mutex); 
    const time_t ctt = time(0); 
    *this << std::setw(40) << std::left << text << " thread id = " << threadID << "\t" << asctime(localtime(&ctt)); // << std::endl; 
} 
+0

我确实有过一个关键部分,但将其作为剥离的一部分删除。在开发这个工作正在进行的日志模块时,我开始出现这个错误。就目前的测试用例而言,它只能在单线程中运行,但是这个问题开始出现并出现。 – zar

+0

如果您有UB并且它不是多线程的,我可以向您保证UB的来源不在显示的代码中。这可能是由于微妙的链接问题,但从您的描述来看,这种规模极不可能。 (尽管如此,请确保您执行完整的清理/重建。) – sehe

+0

由于日志流是全局的,您是否尝试从其他全局数据的构造函数/析构函数中进行记录?您可能会遇到init/shutdown命令问题(请参阅[SIOF](https://isocpp.org/wiki/faq/ctors#static-init-order)) – sehe