显示标签为“VC”的博文。显示所有博文
显示标签为“VC”的博文。显示所有博文

2007年9月7日星期五

SDK中Sample编译错误及其解决方案

SDKSample的编译环境

如果使用Microsoft Visual Studio 2005,在工具->选项->项目和解决方案->vc++目录中进行如下设置。

可执行文件:

D:\Program Files\Microsoft Visual Studio 8\VC

D:\Program Files\Microsoft Visual Studio 8\VC\redist\Debug_NonRedist\x86

\Microsoft.VC80.DebugMFC

D:\Program Files\Microsoft Visual Studio 8\VC\lib

D:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\lib

D:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include

D:\Program Files\Microsoft Visual Studio 8\VC\include

D:\DXSDK\Lib

D:\DXSDK\Bin

D:\DXSDK\Samples\C++\DirectShow\BaseClasses

D:\DXSDK\Samples\C++\Common\Include

D:\DXSDK\Include

包含文件:

D:\Program Files\Microsoft Visual Studio 8\VC\include

D:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include

D:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\Include

D:\DXSDK\Include

D:\DXSDK\Samples\C++\DirectShow\BaseClasses

D:\DXSDK\Samples\C++\Common\Include

库文件:

D:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\Lib

D:\Program Files\Microsoft Visual Studio 8\VC\lib

D:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\lib

D:\Program Files\Microsoft Visual Studio 8\VC

D:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\i386

D:\DXSDK\Lib

D:\DXSDK\Samples\C++\DirectShow\BaseClasses\Debug

D:\DXSDK\Samples\C++\DirectShow\BaseClasses\Release

D:\DXSDK\Samples\C++\DirectShow\BaseClasses

1针对编译DXSDK\Samples\c++\Direct3D时出现的错误,进行解析。

错误例子:

CVTRES : fatal error CVT1100: 重复的资源。type:MANIFEST, name:1, language:0×0409

LINK : fatal error LNK1123: 转换到COFF 期间失败: 文件无效或损坏

解决方案:

我的编译环境是Microsoft Visual Studio 2005

将所有工程的属性(工程全选->右击->属性)->配置属性->清单工具->输入输出->嵌入清单,选择“否”,然后编译,就OK了。

你可以参照微软的官方说明:http://support.microsoft.com/kb/320216/zh-cn

2针对出现未声明标识符的错误进行解析。

错误例子:for( m=0; mdwNumModes; m++ )

{

if( pDevice->modes[m].Width==640 && pDevice->modes[m].Height==480 )

{

error C2065: m: 未声明的标识符

像这种错误,你可以查找它的定义,在将它的定义复制到错误行的前面。如上述例子中,你可以在for的上一行添加long m;。就可以了。

3针对出现无法初始化问题的错误进行解析。

错误例子:

TCHAR* strLastSlash = _tcsrchr( str, TEXT(‘\\’) )

错误:error C2440: “初始化”: 无法从“const wchar_t *”转换为“TCHAR *

像这样的错误,你可以在=的右边进行强制转换。如下:

TCHAR* strLastSlash = (TCHAR*)_tcsrchr( str, TEXT(‘\\’) );

4针对警告被视为错误的问题进行解析。

错误例子:

c:\dxsdk\samples\c++\misc\dxdiagreport\dxdiaginfo.cpp(322) : error C2220: 警告被视为错误- 没有生成“object”文件。

这种错误的原因是:原因是该文件的代码页为英文,而我们系统中的代码页为中文。

解决方案:启动Microsoft Visual Studio 2005,文件->打开->选择c:\dxsdk\samples\c++\misc\dxdiagreport\dxdiaginfo.cpp,然后保存。从新打开程序文件运行,此错误不再出现。

如果上述不能去掉错误,还可以点击项目,右击选择属性->配置属性->c/c++->常规,将“警告视为错误”的选项改为“否”。就可以!

5编译BaseClasses

正在编译

dllentry.cpp

D:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\Include\winnt.h(222) : error C2146: 语法错误: 缺少“;(在标识符“PVOID64”的前面)

D:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\Include\winnt.h(222) : error C4430: 缺少类型说明符- 假定为int。注意: C++ 不支持默认int

D:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\Include\winnt.h(5940) : error C2146: 语法错误: 缺少“;(在标识符“Buffer”的前面)

D:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\Include\winnt.h(5940) : error C4430: 缺少类型说明符- 假定为int。注意: C++ 不支持默认int

D:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\Include\winnt.h(5940) : error C4430: 缺少类型说明符- 假定为int。注意: C++ 不支持默认int

D:\DXSDK\Include\uuids.h : warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为Unicode 格式以防止数据丢失

生成日志保存在“file://d:\BaseClasses\Debug_Unicode\BuildLog.htm

BaseClasses - 5 个错误,个警告

出现错误的地方:

typedef void *PVOID;

typedef void * POINTER_64 PVOID64;

更改:

#define POINTER_64 __ptr64///////gai

typedef void *PVOID;

typedef void * POINTER_64 PVOID64;////

错误:.\wxdebug.cpp(567) : error C4430: 缺少类型说明符- 假定为int。注意: C++ 不支持默认int

错误地方:static g_dwLastRefresh = 0;

修改:static int g_dwLastRefresh = 0;

6编译Capture,无法打开libci.lib

出现错误:LINK : fatal error LNK1104: 无法打开文件“libci.lib

生成日志保存在“file://d:\DXSDK\Samples\C++\DirectShow\Capture\CaptureTex\Debug\BuildLog.htm

CaptureTex - 1 个错误,个警告

错误原因:缺少数据库LIBCI.LIB20032005中已经不存在了

解决方案:将库文件指向VC6中的库文件。

其他详细信息请见

SDK中Sample编译错误及其解决方案(二)


编译Capture

出现错误:LINK : fatal error LNK1104: 无法打开文件“libci.lib

生成日志保存在“file://d:\DXSDK\Samples\C++\DirectShow\Capture\CaptureTex\Debug\BuildLog.htm

CaptureTex - 1 个错误,个警告

错误原因:缺少数据库LIBCI.LIB20032005中已经不存在了

编译DMODEMO

错误:

..\..\..\Common\Src\dsutil.cpp(686) : error C2065: i: 未声明的标识符

错误的地方:

if( i != m_dwNumBuffers )

return m_apDSBuffer[ i ];

else

return m_apDSBuffer[ rand() % m_dwNumBuffers ];

更改:在前面添加 unsigned char i;

编译DMOSAMPLE

d:\DXSDK\include\dmoimpl.h(622) : error C2065: dw: 未声明的标识符

d:\DXSDK\include\dmoimpl.h(588): 编译类模板成员函数“HRESULT IMediaObjectImpl<_derived_,numberofinputs,numberofoutputs>::ProcessOutput(DWORD,DWORD,DMO_OUTPUT_DATA_BUFFER *,DWORD *)”时

with

[

_DERIVED_=CSample,

NUMBEROFINPUTS=1,

NUMBEROFOUTPUTS=2

]

d:\dxsdk\samples\c++\directshow\dmo\dmosample\Sample.h(21): 参见对正在编译的类模板实例化“IMediaObjectImpl<_derived_,numberofinputs,numberofoutputs>”的引用

with

[

_DERIVED_=CSample,

NUMBEROFINPUTS=1,

NUMBEROFOUTPUTS=2

]

d:\DXSDK\include\dmoimpl.h(623) : error C2228: .dwStatus”的左边必须有类/结构/联合

d:\DXSDK\include\dmoimpl.h(624) : error C2228: .fIncomplete”的左边必须有类/结构/联合

d:\DXSDK\include\dmoimpl.h(626) : error C2228: .fIncomplete”的左边必须有类/结构/联合

sample.cpp

d:\DXSDK\include\uuids.h : warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为Unicode 格式以防止数据丢失

d:\DXSDK\include\dmoimpl.h(622) : error C2065: dw: 未声明的标识符

d:\DXSDK\include\dmoimpl.h(588): 编译类模板成员函数“HRESULT IMediaObjectImpl<_derived_,numberofinputs,numberofoutputs>::ProcessOutput(DWORD,DWORD,DMO_OUTPUT_DATA_BUFFER *,DWORD *)”时

with

[

_DERIVED_=CSample,

NUMBEROFINPUTS=1,

NUMBEROFOUTPUTS=2

]

d:\dxsdk\samples\c++\directshow\dmo\dmosample\Sample.h(21): 参见对正在编译的类模板实例化“IMediaObjectImpl<_derived_,numberofinputs,numberofoutputs>”的引用

with

[

_DERIVED_=CSample,

NUMBEROFINPUTS=1,

NUMBEROFOUTPUTS=2

]

d:\DXSDK\include\dmoimpl.h(623) : error C2228: .dwStatus”的左边必须有类/结构/联合

d:\DXSDK\include\dmoimpl.h(624) : error C2228: .fIncomplete”的左边必须有类/结构/联合

d:\DXSDK\include\dmoimpl.h(626) : error C2228: .fIncomplete”的左边必须有类/结构/联合

state.cpp

StdAfx.cpp

util.cpp

正在生成代码

生成日志保存在“file://d:\DXSDK\Samples\C++\DirectShow\DMO\DMOSample\Debug_Unicode\BuildLog.htm

dmosample - 8 个错误,个警告

========== 生成: 0 已成功, 1 已失败, 0 最新, 0 已跳过==========

更改:在出错的语句前加上DWORD_PTR dw;

编译PlayDVD

正在链接

PlayDVD.obj : error LNK2001: 无法解析的外部符号“unsigned int (__stdcall* ATL::g_pfnGetThreadACP)(void)” (?g_pfnGetThreadACP@ATL@@3P6GIXZA)

.\Debug_Unicode/PlayDVD.exe : fatal error LNK1120: 1 个无法解析的外部命令

生成日志保存在“file://d:\DXSDK\Samples\C++\DirectShow\DVD\PlayDVD\Debug_Unicode\BuildLog.htm

PlayDVD - 2 个错误,个警告

========== 全部重新生成: 0 已成功, 1 已失败, 0 已跳过==========

编译DVD

错误:

PlayDVD.obj : error LNK2001: 无法解析的外部符号“unsigned int (__stdcall* ATL::g_pfnGetThreadACP)(void)” (?g_pfnGetThreadACP@ATL@@3P6GIXZA)

.\Debug/PlayDVD.exe : fatal error LNK1120: 1 个无法解析的外部命令

生成日志保存在“file://d:\DXSDK\Samples\C++\DirectShow\DVD\PlayDVD\Debug\BuildLog.htm

PlayDVD - 2 个错误,个警告

========== 生成: 1 已成功, 1 已失败, 0 最新, 0 已跳过==========

无法解决

编译Editing

错误:xmltltst.cpp

d:\DXSDK\include\uuids.h : warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为Unicode 格式以防止数据丢失

.\xmltltst.cpp(291) : error C2065: k: 未声明的标识符

.\xmltltst.cpp(304) : error C2065: j: 未声明的标识符

生成日志保存在“file://d:\DXSDK\Samples\C++\DirectShow\Editing\XTLTest\Debug_Unicode\BuildLog.htm

XTLTest - 2 个错误,个警告

========== 生成: 6 已成功, 1 已失败, 1 最新, 0 已跳过==========

更改:添加unsigned long k = 0 ;

unsigned long j = 0 ;

编译PlayWndASF

错误:

playwndasf.obj : error LNK2001: 无法解析的外部符号“unsigned int (__stdcall* ATL::g_pfnGetThreadACP)(void)” (?g_pfnGetThreadACP@ATL@@3P6GIXZA)

urllaunch.obj : error LNK2001: 无法解析的外部符号“unsigned int (__stdcall* ATL::g_pfnGetThreadACP)(void)” (?g_pfnGetThreadACP@ATL@@3P6GIXZA)

.\Debug_Unicode/PlayWndASF.exe : fatal error LNK1120: 1 个无法解析的外部命令

生成日志保存在“file://d:\DXSDK\Samples\C++\DirectShow\Players\PlayWndASF\Debug_Unicode\BuildLog.htm

PlayWndASF - 3 个错误,个警告

========== 全部重新生成: 1 已成功, 1 已失败, 0 已跳过==========

更改:

向数据库依赖项中添加atlsd.lib

编译demosD:\DXSDK\Samples\C++\Demos

错误:

StdAfx.cpp

d:\program files\microsoft directx sdk (april 2007)\include\d3d9types.h(1385) : warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为Unicode 格式以防止数据丢失

d:\DXSDK\Samples\C++\common\include\D3DFile.h(56) : error C2061: 语法错误: 标识符“LPDIRECTXFILEDATA

d:\DXSDK\Samples\C++\common\include\D3DFile.h(111) : error C2061: 语法错误: 标识符“LPDIRECTXFILEDATA

d:\DXSDK\Samples\C++\common\include\D3DFile.h(113) : error C2061: 语法错误: 标识符“LPDIRECTXFILEDATA

生成日志保存在“file://d:\DXSDK\Samples\C++\Demos\Donuts4\Debug\BuildLog.htm

Donuts4 - 3 个错误,个警告

========== 全部重新生成: 0 已成功, 1 已失败, 0 已跳过==========

更改:dsdfile.h的顶部加入#include 就可以

再次编译出现错误:

.\..\Common\Src\d3dfile.cpp(151) : error C2664: D3DXLoadMeshFromXof: 不能将参数1 从“LPDIRECTXFILEDATA”转换为“LPD3DXFILEDATA

与指向的类型无关;转换要求reinterpret_castC 样式转换或函数样式转换

错误出处:

if( FAILED( hr = D3DXLoadMeshFromXof( pFileData, D3DXMESH_SYSTEMMEM, pd3dDevice,

&pAdjacencyBuffer, &pMtrlBuffer, NULL,

&m_dwNumMaterials, &m_pSysMemMesh ) ) )

更改:

if( FAILED( hr = D3DXLoadMeshFromXof((LPD3DXFILEDATA)pFileData, D3DXMESH_SYSTEMMEM, pd3dDevice,

&pAdjacencyBuffer, &pMtrlBuffer, NULL,

&m_dwNumMaterials, &m_pSysMemMesh ) ) )

编译d3d

编译dxtex

错误:

.\dxtexdoc.cpp(694) : error C2440: “初始化”: 无法从“const char *”转换为“TCHAR *

转换丢失限定符

.\dxtexdoc.cpp(6 8) : error C2440: “初始化”: 无法从“const char *”转换为“TCHAR *

转换丢失限定符

dxtexview.cpp

WINVER not defined. Defaulting to 0×0502 (Windows Server 2003)

d:\program files\microsoft directx sdk (april 2007)\include\d3d9types.h(1385) : warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为Unicode 格式以防止数据丢失

MainFrm.cpp

WINVER not defined. Defaulting to 0×0502 (Windows Server 2003)

d:\program files\microsoft directx sdk (april 2007)\include\d3d9types.h(1385) : warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为Unicode 格式以防止数据丢失

StdAfx.cpp

WINVER not defined. Defaulting to 0×0502 (Windows Server 2003)

d:\program files\microsoft directx sdk (april 2007)\include\d3d9types.h(1385) : warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为Unicode 格式以防止数据丢失

正在生成代码

正在创建浏览信息文件

Microsoft ?????????? Version 8.00.50727

Copyright (C) Microsoft Corporation. All rights reserved.

生成日志保存在“file://d:\DXSDK\Samples\C++\Direct3D\DXTex\Debug\BuildLog.htm

dxtex - 2 个错误,个警告

========== 生成: 0 已成功, 1 已失败, 0 最新, 0 已跳过==========

错误地方: TCHAR* pszLeaf = strrchr(lpszPathName, ‘\\’);

更改TCHAR* pszLeaf = (TCHAR*)strrchr(lpszPathName, ‘\\’);

编译后出现错误:

正在链接

CVTRES : fatal error CVT1100: 重复的资源。type:MANIFEST, name:1, language:0×0409

LINK : fatal error LNK1123: 转换到COFF 期间失败: 文件无效或损坏

更改:

将在Debug模式下编译改为Release模式下编译。

编译Waterwater.cpp)错误:

.\Water.cpp(7 8) : error C2039: Pass: 不是“ID3DXEffect”的成员

更改: 直接去掉这句// m_pEffect->Pass(uPass)

\fur.cpp(424) : error C2039: Pass: 不是“ID3DXEffect”的成员

d:\program files\microsoft directx sdk (april 2007)\include\d3dx9effect.h(316) : 参见“ID3DXEffect”的声明

.\fur.cpp(550) : error C2039: Pass: 不是“ID3DXEffect”的成员

d:\program files\microsoft directx sdk (april 2007)\include\d3dx9effect.h(316) : 参见“ID3DXEffect”的声明

.\fur.cpp(567) : error C2039: Pass: 不是“ID3DXEffect”的成员

d:\program files\microsoft directx sdk (april 2007)\include\d3dx9effect.h(316) : 参见“ID3DXEffect”的声明

.\fur.cpp(585) : error C2039: Pass: 不是“ID3DXEffect”的成员

d:\program files\microsoft directx sdk (april 2007)\include\d3dx9effect.h(316) : 参见“ID3DXEffect”的声明

dxutil.cpp

更改:Pass改成小写pass。在Water编译中也是错误的!!!

编译VertexBlend(vertexblend.cpp)

错误\vertexblend.cpp(312) : error C2065: i: 未声明的标识符

.\vertexblend.cpp(315) : error C2228: .v”的左边必须有类/结构/联合

.\vertexblend.cpp(315) : error C2228: .x”的左边必须有类/结构/联合

.\vertexblend.cpp(316) : error C2228: .blend”的左边必须有类/结构/联合

改正for( INT i=0; i

{

// Set the blend factors for the vertices

FLOAT a = ( pVertices[i].v.x - fMinX ) / ( fMaxX - fMinX );

pVertices[i].blend = 1.0f-sinf(a*D3DX_PI*1.0f);

}///INT




2007年9月6日星期四

Stack corruption

真是看不出来,下面的这段代码引起了栈异常(stack corruption detected)。

{

char cn[60];

memset(cn,0,sizeof(cn));

char defile[FILENAME_MAX+4]={0};

strcpy(defile,localFilename);

strcat(defile,".de");

if (getCommonNameFromFile(localFilename,cn))

{

char *certfile=Singleton<CertList>::instance()->getCertFile(cn);

if (certfile)

{

int nerr=DeFile(localFilename,defile,certfile);

if (nerr==0)

{

//文件验签也OK

//那么,检查E语言

if (pReader==NULL)

{

pReader=new Reader();

}

getLogger()->LogMessage("Session %3d 正在进行E语言检查",id);

ret=pReader->checkEPack(defile);

remove(defile);

return ret;

}

}

}

}

真的好奇怪,这个问题头一次碰到。不就是这么一个auto类型的cn变量,也能出错?真是神了。。。

我把这个cn换成new的堆类型,结果就是堆异常。。。

Google一下,看到这么一篇文章:一个不小心引发的Heap corruption ,还有他的 探索Heap Corruption
大意就是访问,写越界。这里访问到了超过cn[60]的位置,怎么会这样呢??

我仔细看了下代码,发现 原来cn传入的函数中,都认为cn的大小为64。。。

因为64是默认的CommonName的最大长度。这里面一时忘记,写成六十了,结果产生异常。

还好被调试器发现了,要不然还不知道会出现什么恶劣结果呢。


后记:这也告诫我们,最好定义一个大小常量或者宏,每个地方统一用这个产量来定义大小,就不会出错啦

openssl编译小结

呵呵,看得再多,不如自己动手做一下。网上讲的都很好:)

格式大多如下:
2、下载ActivePerl-5.8.0.806-MSWin32-x86并安装:
3、下载 openssl0.98并解压。
安装步骤:完全可以参照openssl目录下的install.win32
1、perl Configure VC-WIN32
如不成功会有明显提示
2、ms\do_ms
推荐使用这种方式
另外两种方式 如果使用也必须保证本机有编译器才能使用。
:ms\do_masm (默认vc 自带的编译器;也也以自己下载安装)
:ms\do_nasm (需要自己下载)
3、DOS窗口下转到【Microsoft Visual Studio】\VC98\bin目录下执行 vcvars32.bat以配置环境变量。
4、跳到openssl目录下,执行:
nmake -f ms\ntdll.mak
如果编译成功,最后的输出都在out32dll目录下:包括可执行文件、两个dll和两个lib文件: libeay32.dll, libeay32.lib, ssleay32.dll, ssleay32.lib
5、 打开VC-Tools-Options-Directores,在Include files中增加【openssl-0.9.8】\inc32目录;在Libray files中增加【openssl-0.9.8】\out32dll
目-〉属性-〉连接-〉输入-〉ssleay32.lib libeay32.lib
在相关目录下增加libeay32.dll, libeay32.lib

有的还有如下说明:

注意:在运行第五步时,cl编译器会抱怨说.\crypto\des\enc_read.c文件的read是The POSIX name for this item is deprecated(不被推荐的),建议使用_read。呵呵,我可不想将OpenSSL中的所有的read函数修改为_read。再看cl的错误代码 error C2220,于是上MSDN上查找:
warning treated as error - no object file generated
/WX tells the compiler to treat all warnings as errors. Since an error occurred, no object or executable file was generated.
是由于设置了/WX选项,将所有的警告都作为错误对待,所以。。。
其实这个WX选项可以不删,因为我用VS2005编译,对C++支持非常好。


另外一个就是,网上教的都是如何编译动态库,难道就不能静态么?
我们发现,在第三步之后,ms目录下的.mk文件有两个,nt.mak 和ntdll.mk。常识使用nt.mk进行生成,果然编译成为静态库!

而且,WX不删除,照样编译没有问题 :)

尽信书不如无书 :)

openssl学习小总结(编译使用)

老 师给我关于openssl方面的材料有快两个星期了,从最初的一无所知,终于在网络的大海洋中找到了自己想要的一点东西,但最初还是懵懵懂懂,因为网上的 一些东西跟opensslforwin.pdf这个全英文文章中的内容不大相同。终于,把这个英文文章翻译了一半(因为后面部分讲解命令的使用),然后再 找自己需要的东西,才发现原来这些东西并不是像想象中的那么难,最主要的只是自己是个门外汉。现将自己的一点心得总结如下:

以下以文章代表opensslforwin.pdf的内容:

1、openssl的编译:
编译有两种方法:一种是网上的,一种是文章中的。
网上的:
1 安装vc6.0 路径为默认都为默认路径。

2 下载 ActivePerl-5.8.0.806-MSWin32-x86 并安装

3下载 openssl0.96i 解压到根目录下 。如c:
(我开始下载的是最新的.97a,但最后编译时候n_pkey.c老是出问题的)

开始安装:
1) > perl Configure VC-WIN32
: 如不成功会有明显提示
2) > ms\do_ms
: 推荐使用这种方式,我第一次成功编译就是在这种方式下
:另外两种方式 如果使用也必须保证本机有编译器才能使用。
: > ms\do_masm (默认vc 自带的编译器;也也以自己下载安装)

: ms\do_nasm (需要自己下载) :


3)转到C:\Program Files\Microsoft Visual Studio\VC98\bin目录(默认安装时)下
执行 vcvars32.bat 以配置环境变量。

4)跳到openssl目录下
执行> nmake -f ms\ntdll.mak
:如果编译成功,最后的输出都在out32dll目录下 : 包括可执行文件 、两个dll和两个lib文件。
文章中的:
1 安装vc6.0 路径为默认都为默认路径。

2 下载 ActivePerl-5.8.0.806-MSWin32-x86 并安装

3下载 openssl0.96i 解压到根目录下 。如c:
(我开始下载的是最新的.97a,但最后编译时候n_pkey.c老是出问题的)
4下载msvc,将其解压到openssl的目录下,下载地址为:http://www.infosecurity.org.cn/forum/read.php?fid=11&tid=301&page=1,要知道这个是针对openssl0.9.7e/f的。

1) > perl Configure VC-WIN32
: 如不成功会有明显提示
2) > ms\do_ms
: 推荐使用这种方式,我第一次成功编译就是在这种方式下
:另外两种方式 如果使用也必须保证本机有编译器才能使用。
: > ms\do_masm (默认vc 自带的编译器;也也以自己下载安装)

: ms\do_nasm (需要自己下载) :


3)转到C:\Program Files\Microsoft Visual Studio\VC98\bin目录(默认安装时)下
执行 vcvars32.bat 以配置环境变量。
4)这时需要使用msvc来进行链接编译:
(1)打开visual c++ 6.0,File->Open Workspace,这时会出现一个对话框,选择要打开的workspace,这时就选择.../openssl-0.9.7e/msvc097/openssl.dsw
(2)点击Build->Batch Build...出现一个对话框如下:
点击Rebuild All。将会进行编译。里面可能会出现几个关于REQ和OCSP方面的错误,adylee说这个可以不用担心。因为我也是一个初学者,所以想可以学得多一点会了解的更多,会知道原因的。所以也就没有过于追究。
完成以后,别忘了把生成所的可执行文件所在的目录,如:C:\openssl0.9.7e\out32dll\release加入到系统环境变量中,这样的话可以在任何目录下来使用这些应用程序。
使用方法如下:
openssl 产生keypair方法

openssl genrsa –out privatekey.pem 1024

Generates a 1024 bit RSA private key and writes it into the file privatekey.pem. The PEM format is widely used for storing keys, certificates etc..

openssl rsa –in privatekey.pem -pubout –out publickey.pem

Generates the corresponding RSA public key and writes it in publickey.pem.

可能是版本问题,感觉文章中说的很多方法并不能直接运行,需要进行少许的修改,但我还是感觉看这个文章还是很有用处的。

Windows下Openssl安装以及编程

Windows下Openssl安装以及编程
1、安装VC++ 6.0。
2、下载ActivePerl-5.8.0.806-MSWin32-x86并安装:
3、下载 openssl0.98并解压。
安装步骤:完全可以参照openssl目录下的install.win32
1、perl Configure VC-WIN32
如不成功会有明显提示
2、ms\do_ms
推荐使用这种方式
另外两种方式 如果使用也必须保证本机有编译器才能使用。
:ms\do_masm (默认vc 自带的编译器;也也以自己下载安装)
:ms\do_nasm (需要自己下载)
3、DOS窗口下转到【Microsoft Visual Studio】\VC98\bin目录下执行 vcvars32.bat以配置环境变量。
4、跳到openssl目录下,执行:
nmake -f ms\ntdll.mak
如果编译成功,最后的输出都在out32dll目录下:包括可执行文件、两个dll和两个lib文件: libeay32.dll, libeay32.lib, ssleay32.dll, ssleay32.lib
5、 打开VC-Tools-Options-Directores,在Include files中增加【openssl-0.9.8】\inc32目录;在Libray files中增加【openssl-0.9.8】\out32dll
目-〉属性-〉连接-〉输入-〉ssleay32.lib libeay32.lib
在相关目录下增加libeay32.dll, libeay32.lib

Windows下Openssl安装以及编程

Windows下Openssl安装以及编程

必备条件:

1、安装VC++ 6.0

2、下载ActivePerl-5.8.0.806-MSWin32-x86并安装:

http://www.sogoz.info/down.asp?id=3683&no=1

3、下载 openssl0.98并解压。

http://www.openssl.org/source/openssl-0.9.8.tar.gz

安装步骤:完全可以参照openssl目录下的install.win32

1perl Configure VC-WIN32

如不成功会有明显提示

2ms\do_ms

推荐使用这种方式

另外两种方式 如果使用也必须保证本机有编译器才能使用。

:ms\do_masm (默认vc 自带的编译器;也也以自己下载安装)

:ms\do_nasm (需要自己下载)

3DOS窗口下转到【Microsoft Visual Studio\VC98\bin目录下执行 vcvars32.bat 以配置环境变量。

4、跳到openssl目录下,执行:

nmake -f ms\ntdll.mak

如果编译成功,最后的输出都在out32dll目录下:包括可执行文件、两个dll和两个lib文件: libeay32.dll, libeay32.lib, ssleay32.dll, ssleay32.lib

注意:在运行第五步时,cl编译器会抱怨说.\crypto\des\enc_read.c文件的read是The POSIX name for this item is deprecated(不被推荐的),建议使用_read。呵呵,我可不想将OpenSSL中的所有的read函数修改为_read。再看cl的错误代码 error C2220,于是上MSDN上查找:
warning treated as error - no object file generated
/WX tells the compiler to treat all warnings as errors. Since an error occurred, no object or executable file was generated.
是由于设置了/WX选项,将所有的警告都作为错误对待,所以。。。




编程初步:

1、 打开VCTools-Options-Directores,在Include files中增加【openssl-0.9.8\inc32目录;在Libray files中增加【openssl-0.9.8\out32dll

2、 在源程序中包含以下三个头文件并加入LIB

#include
#include

#include

#pragma comment(lib, "libeay32.lib")

#pragma comment(lib, "ssleay32.lib")

3、 参考源码开始编程:http://www.kennethballard.com/Download/intro-openssl.zip

error C2059 种种

error C2059 种种

发布者:许超  发表日期:2007-02-07 15:13:23.09



一日遇到C2059错误,google搜索发现C2059的错误表现有多种。

这里整理一些以及自己遇到的情况,供大家借鉴解决。

第一种:


int main )
{
}

它会引起C2059错误,错误信息:error C2059: syntax error : )

第二种:

#include
#define TEST
int main(int argc, char* argv[])
{
#ifdef TEST
printf(\nTEST defined %d, TEST);
#else
printf(\nTEST not defined);
#endif

return 0;
}

它也会引起C2059错误,错误信息:error C2059: syntax error : )

另外一种:

struct ag_type
{
int a;
float b;
};

void func(ag_type arg = {5, 7.0});

它也会引起C2059错误,错误信息:error C2059: syntax error : ) 还会附带error C2143:。

第三种,也是本人遇到的,

刚开始,比较怪异,现象:

1 使用openssl库,在另一个工程里,ok,没问题。

2 在出问题工程里,不在.h文件出现 #include ,ok,正常。

3 在出问题工程里,在.h文件出现 #include 立即出现C2059错误。

此时,在openssl路径配置正确情况下,在某一.h文件只写入

#include

会出现error C2059: syntax error : constant 错误。

解决:

经仔细研究,对比,试验,发现,openssl的头文件有顺序之分。加入下面句子,即

正常。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

根据经验,这是一例头文件互耦比较严重的问题,遇到此种情况,需调整.h文件

出现序列即可解决此类C2059问题。

总结:人们在设计各种规则的同时,隐含的也设计出来了各种烦恼。

人们就是既要享受这些规则带来的好处,也要经受问题的刁扰。

经验告诉我们,利大于弊。

2007年9月5日星期三

VC编译器高级编译技巧

首先,转载一下关于内存泄漏检测的相关技巧,参见:最快速度找到内存泄漏
其主要内容摘录如下:

inline void EnableMemLeakCheck()
{
_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)
| _CRTDBG_LEAK_CHECK_DF);
}

#ifdef _DEBUG
#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endifvoid main()
{
EnableMemLeakCheck();
_CrtSetBreakAlloc(
52);
int* leak = new int[10];
}

原来这里从定义了new,恩,真的很好。可是,我又使用了他的内存组件AutoFreeAlloc(参见C++内存管理变革(3):另类内存管理AutoFreeAlloc规格AutoFreeAlloc细节)。这个组件也是真的很好,真的很好。可是里面对于new,也有类似“重定义”的做法。代码如下:

#define STD_NEW(alloc, Type) \

::new((alloc).allocate(sizeof(Type), \

std::DestructorTraits::destruct)) Type
如果把这里的new替换成我们的new(_NORMAL_BLOCK, __FILE__, __LINE__)的话,在有的情况下会产生编译错误。换句话说,两者不能共存。

这叫什么问题??貌似是宏定义之间的冲突?好像又不是。网上找了老半天,看到一段本地new与托管new共存的代码,参见
经典与现代的结合:在MFC中集成RAD.NET框架
主要内容如下:
  在MFC非托管类中定义托管成员变量

  在MFC类中使用托管对象,提供对象的声明和初始化方法与传统的方法略有不同。以在文档类CtestDoc中添加一个托管成员变量为例,声明托管对象的代码如下:

以下是引用片段:
public:
gcroot m_ptestDocObj;

  gcroot类型安全包装模板可以将托管参考类型指针作为成员变量嵌入到非托管类中,该变量就可以像其他类型的变量一样使用了。在CtestDoc的成员函数InitialDocument中创建这个对象,代码如下:

以下是引用片段:
BOOL CtestDoc::InitialDocument()
{
#pragma push_macro("new")
#undef new
m_ptestDocObj = new test::testDocObject();
#pragma pop_macro("new")
}

  由于testDocObject是一个托管参考类型,它总被分配在CLR堆上,所以自然不能使用在afx.h中定义的new操作符来直接初始化该对象以避免该托管对象在非托管的本地C++堆上创建导致的错误。在托管对象中声明MFC对象,与常规方法一致。


原来如此,VC支持对宏定义的push与pop啊。尝试在用到STD_NEW的地方,就把原来的new定义push起来,undef。然后再把其pop出来。这样,果然编译的很顺利了。

这里还有微软关于pop的文档 pop_macro
主要内容摘录如下:
pop_macro
#pragma pop_macro("macro_name")

Sets the value of the macro_name macro to the value on the top of the stack for this macro. You must first issue a push_macro for macro_name before you can do a pop_macro.

Example

// pragma_directives_pop_macro.cpp
// compile with: /W1
#include
#define X 1
#define Y 2

int main() {
printf("%d",X);
printf("\n%d",Y);
#define Y 3 // C4005
#pragma push_macro("Y")
#pragma push_macro("X")
printf("\n%d",X);
#define X 2 // C4005
printf("\n%d",X);
#pragma pop_macro("X")
printf("\n%d",X);
#pragma pop_macro("Y")
printf("\n%d",Y);
}

Program Output

1
2
1
2
1
3
    对了,我了解那个pop还是从这里了解到的:C++ Q&A 专栏... 性能监视,托管扩展,和锁定工具栏
 我有一个用 C++ 写的库并且我
正在尝试用托管扩展将我的某些类暴露给 Microsoft .NET 框架。这时编译器报错 C3828:“placement arguments
not allowed while creating instances of managed classes”。我必须要在我的库中插入下面的代码
才能解决这个问题: #pragma push_macro("new")
#undef new
// managed stuff here
#pragma pop_macro("new")
  但我始终不明白为什么要这样做,因为我的其它模块不需要它们。此外,敲入 pragmas 相当不方便。有没有什么更好的方法使我不必总是要敲入 push_macro
和 pop_macro?

Jordie Marslan

这个问题与 C++ 无关,它与 MFC 有关。C++ 的一个 比较晦涩难懂的特点是你可以重载 new 操作符,并且你甚至可以给它附加参数。通常,操作符 new 只接受拟分配对象的大小:

void* operator new(size_t nAlloc)
{
return malloc(nAlloc);
}   但你也可以随心所欲附加参数来重载 new 操作符,只要在调用 new 时候提供这些参数即可。在各种应用程序向导(App Wizards)中,这 是 MFC 所做的事情。一个典型的 MFC 程序(.cpp)文件顶部都有下面这样的代码行,通常都由应用程序向导生成: #ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif MFC 将 new 重定义为 DEBUG_NEW。但 DEBUG_NEW 是什么? afx.h 道出了原委: // (simplified)
#ifdef _DEBUG
# define DEBUG_NEW new(THIS_FILE, __LINE__)
#else
# define DEBUG_NEW new
#endif 在 debug 生成模式中,MFC 重载了操作符 new 以获取两个额外的参数,比如: void* operator new(size_t nSize,
LPCSTR lpszFileName, int nLine);   重载的版本与普通的 new 同样都有表示对象大小的 size 参数,但还增加了两个参数:源文件名称和行数。因此,无论何时,只要你写: pfoo = new CFoo(..); 预处理程序便会将它转变为: pfoo = new (sizeof(CFoo), THIS_FILE, __LINE__) CFoo(...);   __FILE__(用来初始化 THIS_FILE)和 __LINE__ 是专用的预处理符号,它保存当前被编译的模块文件名称和行数。 其主要用途是当你的应用程序泄漏时,MFC 能显示一个消息。如: Shame on you! You didn''t free the CFoo object in foo.cpp, line 127!   这对于调试来说,是个巨大的福音,但是当你使用托管C++时,它会导致混乱,因为公共语言运行时(CLR)用于托管对象的 new 操作符并不能理解 这些额外的参数(placement arguments)。但是 MFC 用 #define 重定义了 new,这导致预处理程序做了一个直接的词汇替换。当托管扩展看到了 额外的参数,它们便会歇斯底里。这就是为什么你必须用 #pragmas push_macro/pop_macro 来临时反定义 MFC 已经定义的东西, 然后再次重定义它以恢复到 MFC 中。
  对于这个问题,我能想到的唯一的解决办法就是删除 MFC 对 new 的重定义,同时用某个称为mfcnew 的东西来替代它,如 Figure 2 所示。 其缺点是当分配常规 C++ 对象时,你必须记住使用 mfcnew 类型,而分配托管对象时使用常规的 new 声明,如下所示: pfoo = mfcnew CFoo(...);
CManagedClass *pmc = new CManagedClass();   如果你忘记使用 mfcnew,你便无法获得自动的内存泄漏报告。如果你认为这样是相当麻烦的(我就是这么觉得),那么你会很高兴知道这些问题将在 Visual C++® 2005中得到修正。这正相反:它有一个 gcnew 操作符,你必须用它来分配托管对象。这样就不可能再与普通操作符 new 相冲突了。 以我之见,这是一个更好的方案,因为强制程序员了解何时分配与本地堆对象相对的托管对象是有好处的。此外,它也使得将来在托管堆上分配本地对象成为可能,反之亦然,通过 自动创建相应的使用 GCHandle 或其它必需的代理类。
  你可能想知道为什么这个额外的参数被称为“placement arguments”,这是因为最初的目的是允许你在内存的特定位置分配对象。例如,你可能创建一个操作符 new(size_t size, void* p),它只返回被传递的指针 void* operator new(size_t size, void* p)
{
return p;
} 这时你可以调用 new(p) CFoo ; 如果你想要在 p 位置创建 CFoo 对象,而不是让 malloc 为你分配内存,就可以使用一个指针 p。
  无论如何,你是对的,使用 push/pop_macro 是个痛苦,而且它还使你的代码看起来丑陋。眼下并没有太多的解决办法——尽管另外一个更加简单的方案 是将所有的托管代码和本地代码隔离开来,放到单独的源文件中去并从托管模块中删除 DEBUG_NEW 部分。如果你的代码已经紧密混合时——换句话说,如果你从相同的函数或代码 块创建托管和非托管对象时,这个方法将不再可行。

补记:文章我写到一半的时候,我发现,原来Winx的作者已经给出解决办法了,都怪我当时看的太快,忽略了而已。。。
参见WINX的STD_NEW与MFC共存问题
作者给出办法大致如下:

解决方案

我推荐的解决方案是,删除MFC在源代码文件中的调试代码中的如下语句:

#define new DEBUG_NEW

不过这带来另一个问题,在该源代码文件中发生的内存泄漏,MFC程序无法检测到了。

要解决这个问题也很简单,如果要用到 new 的地方,直接用 DEBUG_NEW 代替好了。例如:

Type* a = new Type(arg1, arg2);

改为

Type* a = DEBUG_NEW Type(arg1, arg2);

个人推荐

我个人的推荐是,不只是在要使用 WINX 的 STD_NEW 时候这样做,而是,所有代码中都使用DEBUG_NEW,而不是直接使用new。



OK,全文完。

Warning C4150的原因和解决办法

Warning C4150的原因和解决办法

今天有同事碰到了这个Warning

Warning C4150

Deletion of pointer to incomplete type 'type'; no destructor called

下面的代码会导致这个问题:

class A;

A *pA = new A();

delete pA; // Warning C4150

这个Warning字面的意思是由于类型是不完全类型(Incomplete Type),因此destructor不会被调用。

其原因是由于前面使用前置声明来声明class A,此时class A并没有完整的定义,编译器只是把A加入到符号表并标记A为一个class,编译器并不知道更多的信息,比如A的大小,有何成员函数等等。在以一般情况下,如果我们只用到A的指针,在特定平台下A的指针大小固定,因此编译器不会报任何错误。然而,在调用delete来删除pA的时候,编译器可以知道pA所指的内存大小,因为内存分配器在内存块中保存了大小信息,可以正确释放A所占据的内存。但是,由于AIncomplete Type,编译器无法知道A所对应的析构函数(destructor),因此不会调用A的析构函数。

解决方法很简单,#include A所在的头文件即可,如果忘记了#include,则会出现此Warning

当然了,还有一种情况是你已经在某个地方调用过A的析构函数了(这种情况不太常见),在这里只需要释放内存即可,所以可以这么写:

class A;

A *pA = new A();

delete (void *)pA;