2012年12月

删除所有侵犯版权的内容

本站一直使用Adsense作为赞助商。数个月前收到Adsense关于部分内容侵权的通知后就一直都没有挂广告了。

最近有空将盗版电影、盗版软件、破解Key之类的博文全部清理掉了。希望是一个新的开始。

CopyFile error code 5 Access is denied

msdn说:

This function fails with ERROR_ACCESS_DENIED if the destination file already exists and has theFILE_ATTRIBUTE_HIDDEN or FILE_ATTRIBUTE_READONLY attribute set.

如果目标文件已经存在且是隐藏或是只读文件,返回错误号5,禁止访问。

Debug Assertion Failed! File: dbgdel.cpp Line: 47 _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

---------------------------
Microsoft Visual C++ Debug Library
---------------------------
Debug Assertion Failed!

Program: D:\dev\out\test.exe
File: dbgdel.cpp
Line: 47

Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.

(Press Retry to debug the application)
---------------------------
中止(A)   重试(R)   忽略(I)   
---------------------------

原因找到了。PTCHAR test = new TCHAR[1024]之后使用了test++之类的语句后delete[] test。 这样delete指向的并非test的头。所以报错。可以在new完之后用一个PTCHAR来保存head pointer: testHead = test。 然后delete[] testHead。

CFileDialog造成的Access Violation (PSDK 2003 Febrary)

问题:

使用VC6写一个MFC程序,使用2003 Febrary PSDK。结果无端端出现Access Violation保存。但是代码看起来无任何问题。

do
{
    TCHAR   pszFilter[]     =   _T("Test File (*.test)|*.test||");
    CFileDialog* dlg = new CFileDialog(TRUE, NULL, NULL, NULL, pszFilter, this);        
    if(dlg->DoModal() != IDOK)
        break;
    
    CString strPath = dlg->GetPathName();
    m_source.SetWindowText(strPath);
}while(FALSE);

经过一阵google之后发现是CFileDialog是通过 GetOpenFileName 来实现的。GetOpenFileName的参数是结构体,OPENFILENAME。定义了_WIN32_WINNT >= 0x500(也就是win2k版本及其以上)时就会多出三个结构体成员。但是mfc42里面并没有定义这三个结构体成员。造成了访问违例。

#if (_WIN32_WINNT >= 0x0500)
  void          *pvReserved;
  DWORD         dwReserved;
  DWORD         FlagsEx;
#endif 

解决方法有多个:

  1. 不要使用CFileDialog,而是使用GetOpenFileName来实现,推荐。
  2. 去掉#define _WIN32_WINNT,不推荐,因为使用更高版本的PSDK,不就是为了使用新版本的功能,支持更高的系统(XP、Server 2003)吗?
  3. 用new来分配内存:CFileDialog* dlg = new CFileDialog(xxxxxx...........),别忘了用完了delete掉。推荐。

关于此问题的讨论Sheng Jiang(一个牛逼的经常在msdn answer、csdn混迹的人)的回答是:

There is a problem in old versions of MFC: CFileDialog's size in your program is changed by a new version of SDK and no longer match the size in MFC dlls. Paul diLascia in the "C++ Q & A" of August 2000 MSDN Magazine discussed this problem。 Upgrade to Visual C++ 2002 or higher, Create the dialog on the heap, or use the API GetOpenFileName.

Yes,m_ofn is changed to m_pofn and will be always allocated on the heap in later MFC versions.(mfc42后续版本将m_ofn修改为一个在heap上创建的指针,所以不存在该问题了)

参考:

  • CFileDialog退出时异常

  • CFileDialog crash in Platform SDK

  • [VC++ 6.0] Getting 0xC0000005 Access Violation from CFileDialog - Troubleshootin' ain't no joke

  • 装了 Platform SDK 的进来讨论问题 深入的讨论原因!

  • Why CFileDialog crashed with _WIN32_WINNT defined ahead in platform SDK 2003Why CFileDialog crashed with _WIN32_WINNT defined ahead in platform SDK 2003 透过修改MFC\Include\AFXDLGS.H ,和MFC42.dll保持一致来解决问题。