快捷搜索:

您的位置:澳门新葡4473网站 > 项目 > GetDIBits 提示堆栈损坏的解决办法

GetDIBits 提示堆栈损坏的解决办法

发布时间:2019-11-26 12:41编辑:项目浏览(121)

    ......
    
    BITMAPINFOHEADER bi;
    
    bi.biSize = sizeof(BITMAPINFOHEADER);
    bi.biWidth = bmpScreen.bmWidth;
    bi.biHeight = bmpScreen.bmHeight;
    bi.biPlanes = 1;
    bi.biBitCount = bmpScreen.bmBitsPixel; 
    bi.biCompression = BI_RGB;
    bi.biSizeImage = 0;
    bi.biXPelsPerMeter = 0;
    bi.biYPelsPerMeter = 0; 
    bi.biClrUsed = 0; 
    bi.biClrImportant = 0; 
    
    DWORD dwBmpSize = ((bmpScreen.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmpScreen.bmHeight;  cBmpData = new unsigned char[dwBmpSize ]; 
    
    GetDIBits(hdcScreen, hbmScreen, 0, (UINT)bmpScreen.bmHeight, cBmpData, (BITMAPINFO *)&bi, DIB_RGB_COLORS); 
    
    DeleteObject(bmpScreen); 
    
    ReleaseDC(hdcScreen); 
    
    return cBmpData; 
    } <---运行到这里时提示堆栈损坏
    

    磁盘文件排序
    主题材料叙述,来自《编制程序珠玑》:
    输入:多少个最多蕴含n个不雷同的正整数的文件,在那之中每一个数都自暴自弃等于n,且n=10^7。
    输出:得到按从小到大升序排列的隐含全部输入的寸头的列表。
    原则:最多有差不离1MB的内部存款和储蓄器空间可用,但磁盘空间丰裕。且必要运维时刻在5分钟以下,10秒为超级结果。

    这是因为实在GetDIBits的第五个参数需要的其实是一个BITMAPINFO结构,而我们传入的是BITMAPINFOHEADER。

    分析:

    如果在位图不低于贰拾个人时,那是行得通的。不过在位图小于15位时,它还索要此外的内部存款和储蓄器空间来囤积三个调色板数据,所以就能够生出仓库损坏的大谬不然。

    1、归拢列排在一条线序。你或者会想到把磁盘文件进行归总列排在一条线序,但难题必要中,你唯有1MB的内部存款和储蓄器空间可用,所以,归拢列排在一条线序那几个法子丰硕。

    是的的做法是这么的

    2、位图方案。举例正如《编制程序珠玑》生机勃勃书上所述,用三个19人长的位字符串来代表三个有着因素都自愧弗如20的简短的非负整数集合,边框用如下字符串来代表集合{1,2,3,5,8,13}:
    0 1 1 1 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0
    上述集合中各数对应的岗位则置1,未有相应的数的任务则置0。

    struct { BITMAPINFO info; RGBQUAD moreColors[255]; } fbi;
    BITMAPINFOHEADER &bi = fbi.info.bmiHeader;
    bi.biSize = sizeof(BITMAPINFOHEADER);
    ...
    GetDIBits(..., &fbi.info, ...);
    

    参谋《编制程序珠玑》意气风发书上的位图方案,针对10^7个数据量的磁盘文件排序难题,能够如此构思,由于各类7位十进制整数表示多个低于1000万的整数。能够采用叁个兼有1000万个位的字符串来代表那些文件,在那之中,当且仅当整数i在文书中存在时,第i位为1。选用这么些位图的方案是因为大家直面的这么些难题的特殊性:1、输入数据节制在相对相当小的限量内,2、数据还没重新,3、个中的每条记下都以纯净的正整数,未有别的其余与之提到的数额。
    所以,此主题素材用位图的方案分为以下三步举行缓慢解决:
    首先步,将富有的位都置为0,进而将汇集起来化为空。
    第二步,通过读入文件中的每种整数来确立汇聚,将每种对应的位都置为1。
    其三步,核实每一位,若是该位为1,就输出对应的整数。
    透过以上三步后,发生有序的出口文件。令n为位图向量中的位数(本例中为10000000卡塔尔国,程序能够用伪代码表示如下:

     

    //第一步,将所有的位都初始化为0   
    for i ={0,....n}  
        bit[i]=0;  
    
    //第二步,通过读入文件中的每个整数来建立集合,将每个对应的位都置为1。   
    for each i in the input file  
        bit[i]=1;  
    
    //第三步,检验每一位,如果该位为1,就输出对应的整数。   
    for i={0...n}  
        if bit[i]==1  
          write i on the output file  
    

    然则异常的快,大家就将开采到,用此位图方法,严苛说来照旧不太行,空间消耗10^7/8依旧超过1M(1M=1024*1024空间,小于10^7/8)。
    既然如此即使用位图方案以来,大家须求约1.25MB(若每条记下是8位的正整数的话,则10000000/(1024*1024*8) ~= 1.2M卡塔 尔(阿拉伯语:قطر‎的空中,而这段日子只有1MB的可用存款和储蓄空间,那么终归该作哪儿理吧?能够每每运用位图举行排序。

    3、多路合併。把那几个文件分为若干朗朗上口的几块,然后分别对每一块进行排序,最终做到全部经过的排序。k趟算法可以在kn的光阴支付内和n/k的长空开拓内产生对最多n个小于n的无重复正整数的排序。比方可分为2块(k=2,1趟左右占用的内部存款和储蓄器独有1.25/2=0.625M卡塔 尔(英语:State of Qatar),1~4999999,和5000000~9999999先遍历大器晚成趟,管理1~4999999的数据块(用5000000/8=625000个字的仓库储存空间来排序0~4999999之间的整数卡塔 尔(阿拉伯语:قطر‎,然后再第二趟,对5000001~1000000那风流倜傥数目块拍卖。

    针对这些要分两趟给磁盘文件排序的切实可行难点编写完整代码,如下:

    图片 1图片 2View Code

    //copyright@ yansha     
    //July、2010.05.30。     
    //位图方案解决10^7个数据量的文件的排序问题     
    //如果有重复的数据,那么只能显示其中一个 其他的将被忽略     
    #include <iostream>     
    #include <bitset>     
    #include <assert.h>     
    #include <time.h>     
    using namespace std;    
    
    const int max_each_scan = 5000000;    
    
    int main()    
    {    
        clock_t begin = clock();    
        bitset<max_each_scan> bit_map;    
        bit_map.reset();    
    
        // open the file with the unsorted data     
        FILE *fp_unsort_file = fopen("data.txt", "r");    
        assert(fp_unsort_file);    
        int num;    
    
        // the first time scan to sort the data between 0 - 4999999     
        while (fscanf(fp_unsort_file, "%d ", &num) != EOF)    
        {    
            if (num < max_each_scan)    
                bit_map.set(num, 1);    
        }    
    
        FILE *fp_sort_file = fopen("sort.txt", "w");    
        assert(fp_sort_file);    
        int i;    
    
        // write the sorted data into file     
        for (i = 0; i < max_each_scan; i++)    
        {    
            if (bit_map[i] == 1)    
                fprintf(fp_sort_file, "%d ", i);    
        }    
    
        // the second time scan to sort the data between 5000000 - 9999999     
        int result = fseek(fp_unsort_file, 0, SEEK_SET);    
        if (result)    
            cout << "fseek failed!" << endl;    
        else    
        {    
            bit_map.reset();    
            while (fscanf(fp_unsort_file, "%d ", &num) != EOF)    
            {    
                if (num >= max_each_scan && num < 10000000)    
                {    
                    num -= max_each_scan;    
                    bit_map.set(num, 1);    
                }    
            }    
            for (i = 0; i < max_each_scan; i++)    
            {    
                if (bit_map[i] == 1)    
                    fprintf(fp_sort_file, "%d ", i + max_each_scan);    
            }    
        }    
    
        clock_t end = clock();    
        cout<<"用位图的方法,耗时:"<<endl;    
        cout << (end - begin) / CLK_TCK << "s" << endl;    
        fclose(fp_sort_file);    
        fclose(fp_unsort_file);    
        return 0;    
    }    
    

    上述的位图方案,共索要扫描输入数据一次,具体实行步骤如下:
    第四回,只管理1—4999999里边的数额,这一个数都以低于5000000的,对那一个数实行位图排序,只要求约5000000/8=625000Byte,也等于0.625M,排序后输出。
    第4回,扫描输入文件时,只管理4999999-10000000的多少项,也只必要0.625M(能够运用第4回拍卖申请的内部存款和储蓄器卡塔 尔(英语:State of Qatar)。由此,总共也只必要0.625M。

    磁盘文件排序的C完毕

    1、内排序
    是因为必要的可用内部存款和储蓄器为1MB,那么每趟能够在内部存款和储蓄器中对250K的数据进行排序,然后将长久以来的数写入硬盘。
    那么10M的多少须求循环叁十六次,最后发生叁二十一个不改变的文本。

    2、多路合併列排在一条线序
    (1卡塔 尔(阿拉伯语:قطر‎将各样文件最伊始的数读入(由于有序,所感到该公文最小数卡塔 尔(英语:State of Qatar),贮存在三个大大小小为40的first_data数组中;
    (2)选择first_data数组中细小的数min_data,及其对应的公文索引index;
    (3)将first_data数组中型Mini小的的数写入文件result,然后更新数组first_data(依照index读取该公文下三个数替代min_data);
    (4卡塔尔剖断是还是不是有所数据都读取完毕,否则再次来到(2卡塔尔国。

    完全代码如下:

    图片 3图片 4View Code

    //copyright@ yansha   
    //July、updated,2011.05.28。   
    #include <iostream>   
    #include <string>   
    #include <algorithm>   
    #include <time.h>   
    using namespace std;  
    
    int sort_num = 10000000;  
    int memory_size = 250000;  //每次只对250k个小数据量进行排序   
    
    int read_data(FILE *fp, int *space)  
    {  
        int index = 0;  
        while (index < memory_size && fscanf(fp, "%d ", &space[index]) != EOF)  
            index++;  
    
        return index;  
    }  
    
    void write_data(FILE *fp, int *space, int num)  
    {  
        int index = 0;  
        while (index < num)  
        {  
            fprintf(fp, "%d ", space[index]);  
            index++;  
        }  
    }  
    
    // check the file pointer whether valid or not.   
    void check_fp(FILE *fp)  
    {  
        if (fp == NULL)  
        {  
            cout << "The file pointer is invalid!" << endl;  
            exit(1);  
        }  
    }  
    
    int compare(const void *first_num, const void *second_num)  
    {  
        return *(int *)first_num - *(int *)second_num;  
    }  
    
    string new_file_name(int n)  
    {  
        char file_name[20];  
        sprintf(file_name, "data%d.txt", n);  
        return file_name;  
    }  
    
    int memory_sort()  
    {  
        // open the target file.   
        FILE *fp_in_file = fopen("data.txt", "r");  
        check_fp(fp_in_file);  
    
        int counter = 0;  
        while (true)  
        {  
            // allocate space to store data read from file.   
            int *space = new int[memory_size];  
            int num = read_data(fp_in_file, space);  
    
            // the memory sort have finished if not numbers any more.   
            if (num == 0)  
                break;  
    
            // quick sort.   
            qsort(space, num, sizeof(int), compare);  
    
            // create a new auxiliary file name.   
            string file_name = new_file_name(++counter);  
            FILE *fp_aux_file = fopen(file_name.c_str(), "w");  
            check_fp(fp_aux_file);  
    
            // write the orderly numbers into auxiliary file.   
            write_data(fp_aux_file, space, num);  
    
            fclose(fp_aux_file);  
            delete []space;  
        }  
        fclose(fp_in_file);  
    
        // return the number of auxiliary files.   
        return counter;  
    }  
    
    void merge_sort(int file_num)  
    {  
        if (file_num <= 0)  
            return;  
    
        // create a new file to store result.   
        FILE *fp_out_file = fopen("result.txt", "w");  
        check_fp(fp_out_file);  
    
        // allocate a array to store the file pointer.   
        FILE **fp_array = new FILE *[file_num];  
    
        int i;  
        for (i = 0; i < file_num; i++)  
        {  
            string file_name = new_file_name(i + 1);  
            fp_array[i] = fopen(file_name.c_str(), "r");  
            check_fp(fp_array[i]);  
        }  
    
        int *first_data = new int[file_num]; //new出个大小为0.1亿/250k数组,由指针first_data指示数组首地址   
    
        bool *finish = new bool[file_num];  
        memset(finish, false, sizeof(bool) * file_num);  
    
        // read the first number of every auxiliary file.   
        for (i = 0; i < file_num; i++)  
            fscanf(fp_array[i], "%d ", &first_data[i]);  
    
        while (true)  
        {  
            int index = 0;  
            while (index < file_num && finish[index])  
                index++;  
    
            // the finish condition of the merge sort.   
            //要保证所有文件都读完,必须使得finish[0]...finish[40]都为真   
            if (index >= file_num)  
                break;  
    
            int min_data = first_data[index];  
    
            // choose the relative minimum in the array of first_data.   
            for (i = index + 1; i < file_num; i++)  
            {  
                if (min_data > first_data[i] && !finish[i])//比min_data更小的数据first_data[i]   
                {  
                    min_data = first_data[i];    //则置min_data<-first_data[i]   
                    index = i;                   //把下标i 赋给index。   
                }  
            }  
    
            // write the orderly result to file.   
            fprintf(fp_out_file, "%d ", min_data);  
    
            if (fscanf(fp_array[index], "%d ", &first_data[index]) == EOF)  
                finish[index] = true;  
        }  
    
        fclose(fp_out_file);  
    
        delete []finish;  
        delete []first_data;  
    
        for (i = 0; i < file_num; i++)  
            fclose(fp_array[i]);  
    
        delete [] fp_array;  
    }  
    
    int main()  
    {  
        clock_t start_memory_sort = clock();  
        int aux_file_num = memory_sort();  
        clock_t end_memory_sort = clock();  
        cout << "The time needs in memory sort: " << end_memory_sort - start_memory_sort << endl;  
    
        clock_t start_merge_sort = clock();  
        merge_sort(aux_file_num);  
        clock_t end_merge_sort = clock();  
        cout << "The time needs in merge sort: " << end_merge_sort - start_merge_sort << endl;  
        system("pause");  
        return 0;  
    }  
    

    测验数据:生成1000万个不重复的正整数

    图片 5图片 6View Code

    //生成随机的不重复的测试数据   
    #include <iostream>   
    #include <time.h>   
    #include <assert.h>   
    using namespace std;  
    
    //产生[l,u]区间的随机数   
    int randint(int l, int u)  
    {  
     return l+(RAND_MAX*rand()+rand())%(u-l+1);  
    }  
    
     //1000W的int,大约4M的数据,如果放在mian内,在我的机子上好像是栈溢出了,放在全局空间就没问题   
    const int size = 10000000;  
    int num[size];  
    
    int main()  
    {  
        int i, j;  
        FILE *fp = fopen("data.txt", "w");  
        assert(fp);  
        for (i = 0; i < size; i++)  
            num[i] = i+1;  
        srand((unsigned)time(NULL));  
        for (i = 0; i < size; i++)  
        {  
            j = randint(i, size-1);  
            int t = num[i]; num[i] = num[j]; num[j] = t;  
            //swap(num[i], num[j]);   
        }  
        for (i = 0; i < size; i++)  
            fprintf(fp, "%d ", num[i]);  
        fclose(fp);  
        return 0;  
    }  
    

     

     

    本文由澳门新葡4473网站发布于项目,转载请注明出处:GetDIBits 提示堆栈损坏的解决办法

    关键词: