none
Released编译通过而Debug编译出错:Access violation reading location XXXX RRS feed

  • 问题

  • 用Windows API编写扫雷小游戏的时候,发现编译器本身可能有BUG,不知有否高人帮看一下……

    为了能更清楚的表明问题,另写了一个小程序把问题单独摆出来了。文件如下:

    (系统信息:Windows 7 旗舰版 Service Pack 1

                      Microsoft Visual Studio 2010 Professional Version 10.0.40219.1 SP1Rel)

    // randerror.cpp : Defines the entry point for the application.
    //

    #include "stdafx.h"
    #include "randerror.h"
    #include "stdio.h"
    #include <ctime>
    #define N 18
    #define PCTG 15
    typedef unsigned char GRID;
    //   0    0    0    0    0    0    0    0
    //   0    0    0    0    0  mine | operation
    //mine:       0表示无地雷  1表示有地雷
    //operation: 00表示未操作 01表示有旗帜 10表示有问号 11表示已挖开  

    // Global Variables:
    GRID grid[N][N];

    int APIENTRY _tWinMain(HINSTANCE hInstance,
                         HINSTANCE hPrevInstance,
                         LPTSTR    lpCmdLine,
                         int       nCmdShow)
    {
    int M=(int)(N*N*PCTG*0.01);
    for(int i=0;i<N*N;i++){**(grid+i)=0;}
    srand((unsigned)time(0));
    for(int i=0;i<M;){
    int m=rand()%(N*N);
    if(!grid[m/N][m%N]){grid[m/N][m%N]|=4;i++;}
    }




    TCHAR buf[10000]={0};
    for(int i=0;i<N;i++)
    {
    for(int j=0;j<N;j++)wsprintf(buf,L"%s%d ",buf, grid[i][j]);
    wsprintf(buf,L"%s\n", buf);
    }
    MessageBox(NULL, (LPCWSTR)buf, L"输出", MB_OK);


    }

    出现的问题是:在released状态下程序不会出错,在debug状态下,出现如下提示:

    Unhandled exception at 0x55299602 (msvcr100d.dll) in MineSweeper.exe: 0xC0000005: Access violation reading location 0x8b0680d0.

    程序中设置若干断点调试后,确定错误出现在

    int m=rand()%(N*N);

    这一句。

    单句执行时,编译器会给我看几个系统文件,从我原来那个扫雷小程序的入栈的函数调用信息看,出错位置的父调用函数的父调用者是kernel32.dll,但这里的示意小程序则出错应在

    TCHAR buf[10000]={0};
    for(int i=0;i<N;i++)

    两句之间,因为前一句设断点可以执行到,后一句设断点则无法执行到,出现错误提示如下:

    Unhandled exception at 0x57f81aed (msvcr100d.dll) in randerror.exe: 0xC0000005: Access violation reading location 0x6666665c.

    2013年3月2日 10:20

答案

  • for(int i=0;i<N*N;i++){**(grid+i)=0;}

    改成

    for(int i=0;i<N;i++){
      for( int j = 0; j < N; j++)
      grid[i][j]=0;
     }

    或者

    unsigned char* p = reinterpret_cast<unsigned char*>(grid);
     for(int i=0;i<N*N;i++){
      *(p+i)=0;
     }

    原因是你想将二维数组按照指针的形式赋值,那就要按照首地址向后开始向地址赋值。grid+i是偏移的地址,那么这个地址取值就应该是对应的数值。但你**取值又取值还是按照二维数组访问,就使得改写了程序其他位置的内存。后面一定错了。


    麻烦把正确答案设为解答。


    2013年3月4日 4:04
    版主

全部回复

  • for(int i=0;i<N*N;i++){**(grid+i)=0;}

    改成

    for(int i=0;i<N;i++){
      for( int j = 0; j < N; j++)
      grid[i][j]=0;
     }

    或者

    unsigned char* p = reinterpret_cast<unsigned char*>(grid);
     for(int i=0;i<N*N;i++){
      *(p+i)=0;
     }

    原因是你想将二维数组按照指针的形式赋值,那就要按照首地址向后开始向地址赋值。grid+i是偏移的地址,那么这个地址取值就应该是对应的数值。但你**取值又取值还是按照二维数组访问,就使得改写了程序其他位置的内存。后面一定错了。


    麻烦把正确答案设为解答。


    2013年3月4日 4:04
    版主
  • for(int j=0;j<N;j++)wsprintf(buf,L"%s%d ",buf, grid[i][j]);
    wsprintf(buf,L"%s\n", buf);
    ---------------------------------------
    用自身的数据格式化自身,不觉得有问题吗?

    Visual C++ enthusiast, like network programming and driver development. At present is being engaged in the WinCE/Windows Mobile platform embedded development.

    2013年3月4日 4:56
    版主