• 简单的多线程(活用OD解决运行时错误)


    代码源自《VC++深入详解》第15章 “多线程”,位于第563页 - 566 页。

    程序的目的是展示多线程运行的效果:

    #include <windows.h>
    #include <iostream.h>
    
    DWORD WINAPI Fun1Proc(
      LPVOID lpParameter   // thread data
    );
    
    int index = 0;
    
    int main()
    {
        HANDLE hThread1;
        hThread1 = CreateThread( NULL,0,Fun1Proc,NULL,0,NULL );
        CloseHandle( hThread1 );
        while ( index++ < 1000 )
            cout << "main thread is running." << endl;
    
        return 0;
    }
    
    DWORD WINAPI Fun1Proc(
      LPVOID lpParameter   // thread data
    )
    {
        while ( index++ < 1000 )
            cout << "thread1 is running" << endl;
    
        return 0;
    }
     

    运行时却发现程序崩溃了:

    单击取消用OD调试:

    发现程序是因为读一个0地址的内存引发了异常。在VC6中F5调试程序:

    黄箭头指向的代码中对指针p解引用,而p的的值为0,这引发了异常。右击打开文件的属性,查看文件名:

    是一个C语言文件,文件名为WRITE,写入的意思。我们的程序什么操作用到了写入呢?没错!用到了cout向屏幕输出字符串。

    将#include 语句改为标准格式:

    #include <windows.h>
    #include <iostream>
    
    using namespace std;
    
    DWORD WINAPI Fun1Proc(
      LPVOID lpParameter   // thread data
    );
    
    int index = 0;
    
    int main()
    {
        HANDLE hThread1;
        hThread1 = CreateThread( NULL,0,Fun1Proc,NULL,0,NULL );
        CloseHandle( hThread1 );
        while ( index++ < 1000 )
            cout << "main thread is running." << endl;
    
        return 0;
    }
    
    DWORD WINAPI Fun1Proc(
      LPVOID lpParameter   // thread data
    )
    {
        while ( index++ < 1000 )
            cout << "thread1 is running" << endl;
    
        return 0;
    }

    就可以完美运行:

    然而,这是为什么呢?我们只是猜到出问题的地址,并不了解其中的原理。尝试着百度一下:

    iostream.h与iostream是不同的。
    #include<iostream.h>是在旧的标准C++中使用。在新标准中,用#include<iostream>。iostream的意思是输入输出流。#include<iostream>是标准的C++头文件,任何符合标准的C++开发环境都有这个头文件。还要注意的是:在VC编程时要添加:
    using namespace std;
    其原因是:后缀为.h的头文件C++标准已经明确提出不支持了,早些的实现将标准库功能定义在全局空间里,声明在带.h后缀的头文件里,C++标准为了和C区别开,也为了正确使用命名空间,规定头文件不使用后缀.h。因此,当使用<iostream.h>时,相当于在C中调用库函数,使用的是全局命名空间,也就是早期的C++实现;当使用<iostream>的时候,该头文件没有定义全局命名空间,必须使用namespace std;这样才能正确使用cout。

    关系

    <string.h>是旧的C头文件,对应的是基于char*的字符串处理函数;<string>是包装了std的C++头文件,对应的是新的string类;<cstring>是对应旧的C头文件的std版本。而<iostream.h>和<iostream>的关系,类似于<string.h>和<cstring>的关系,实现的功能是相同的,主要是是否使用命名空间std的区别。
    原因就是我们使用了C++标准不支持的.h头文件,而其中的处理函数则是C语言编写的,这样基于char*的处理函数在多线程时很可能出现大问题,还是用<iostream>比较安全,也比较符合标准。
    我们一路奋战,不是为了改变世界,而是不让世界改变我们 ——《熔炉》
  • 相关阅读:
    Scrum框架及其背后的原则(上)——Scrum 框架的伪代码描述[转载自InfoQ]
    用程序给闺女出算数题——我的头脑体操
    敏捷实践调查结果[翻译转载]
    一.初识Selenium
    二.Selenium安装相关文件
    Review of American Beauty(unoriginal)
    三.Selenium IDE学习
    将Java Project转变为Dynamic Web Project
    功能自动化工具watiJ(转载)
    Selenium前奏
  • 原文地址:https://www.cnblogs.com/ZRBYYXDM/p/5214683.html
Copyright © 2020-2023  润新知