ホーム » メモ (ページ 20)
「メモ」カテゴリーアーカイブ
MFC 追加でメモリリーク
MFC を利用しないコードを VC 6 でテストしていて,
コンソール AP として作成したスケルトンに,::oGetFileSize を追加.
MFC を利用した,::GetFileSize と動作を比べるために,
プロジェクトの設定を変更(共有 DLL で MFC を使用).
main 関数が存在するソースに Afx.h などの include を追加.
ビルドして実行すると,メモリリークが発生するようになった.
main 関数内を全てコメントにしてもあまり変わらない.
MFC サポートありで,コンソール AP を作成.
同様に oGetFileSize と GetFileSize を追加.
ビルド,実行すると特に問題ない.
StdAfx.h 内の Afx.h などを tmain のソース内に移動.
リビルドすると,メモリリーク発生.
どうも,Afx.h より前の iostream などが関係している.
また,リビルドしないと現象が変わらない.
StdAfx.h に iostream の include を追加
#define VC_EXTRALEAN
#include <iostream>
#include <afx.h>
Detected memory leaks! Dumping objects -> {51} normal block at 0x00032440, 33 bytes long. Data: < C > 00 43 00 CD CD CD CD CD CD CD CD CD CD CD CD CD {50} normal block at 0x00034F68, 40 bytes long. Data: < |L > 14 7C 4C 10 16 00 00 00 00 00 00 00 00 00 00 00 Object dump complete. スレッド 0x1218 終了、終了コード 0 (0x0)。 プログラム 'C:\...\T_Con2\Debug\T_Con2.exe' はコード 0 (0x0) で終了しました。
iostream のインクルードを afx.h より後にすることで対応.
open で errno = 13
ファイルにより,open で errno に 13 EACCES Permission denied が設定される.
bool Get_fstat (LPCTSTR name,struct stat* fs) {
if (fs == NULL) { return false ; }
int fh = _topen(name,O_RDONLY) ;
if (fh < 0) { i_Dump(errno) ; }
if (fh < 0) { return false ; }
memset(fs,0,sizeof(struct stat)) ;
int ret = fstat(fh,fs) ;
_close(fh) ;
return (ret == 0) ;
}
__FILE__ などは期待した動作だが,c:\pagefile.sys でエラーとなった.
VC 6 では,~\VC98\CRT\SRC\OPEN.C で CreateFile を呼出している.
その時の値は,
fileaccess 0x80000000
fileattrib 0x00000080
filecreate 0x00000003
fileshare 0x00000003
osfh 0x0013fef0
+ path 0x000326d1 “c:\pagefile.sys”
+ &SecurityAttributes 0x0013fdbc
circle.svg の Load で…
circle.svg の Load で,
‘System.Xml.XmlException’ の初回例外が System.Xml.dll で発生しました。
‘System.Xml.XmlException’ のハンドルされていない例外が System.Xml.dll で発生しました。
追加情報: セキュリティ上の理由から、DTD はこの XML ドキュメントでは使用できません。
DTD 処理を有効にするには、XmlReaderSettings の ProhibitDtd プロパティを False に設定し、XmlReader.Create メソッドにその設定を渡してください。
<?xml version=”1.0″ standalone=”no”? >
<!DOCTYPE svg PUBLIC “-//W3C//DTD SVG 1.1//EN” “http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd” >
<svg width=”320pt” height=”224pt” viewBox=”0 0 100 70″ xmlns=”http://www.w3.org/2000/svg” >
<circle cx=”30″ cy=”25″ r=”20″ fill=”orange”/>
<circle cx=”50″ cy=”35″ r=”20″ stroke-width=”4″ stroke=”brown” fill=”coral”/>
<circle cx=”70″ cy=”45″ r=”20″ stroke-width=”4″ stroke=”chocolate” fill=”none”/>
</svg>
これは,MSXML.dll を利用した場合も正しく読み込めていない(Xml_Import で対応).
Xml_Fnc.hxx の Xml_Import を MFC を利用しない様に書き直した時にもう一度考える.
現状の XmlI_MS や Xml_CLI は,DTD などが付加された xml には対応していない(Xml_Import では可能).
C4793 , C4279
Win 32 コンソール AP で MFC サポートのプロジェクトを作成.
/clr を有効にして,以下のコードで,
// L_xml_K.cpp : コンソール アプリケーションのエントリ ポイントを定義します。 #include "StdAfx.h" #include "L_xml_K.h" #include "Xml_CLI.hxx" #include "XmlOut.hxx" #include "Xml_MS_.hxx" #undef GetTempPath #using <System.dll> #ifdef _DEBUG #define new DEBUG_NEW #endif // 唯一のアプリケーション オブジェクトです。 CWinApp theApp; using namespace std; int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { int nRetCode = 0; if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)) { _tprintf(_T("致命的なエラー: MFC の初期化ができませんでした。\n")); nRetCode = 1; } else { System::String^ tmp = System::IO::Path::GetTempPath() ; System::String^ url = tmp + "211626.svg" ; tstring inXml = ::to_tstring(url) ; Xml_E xe_CLI = XmlI_CLI::Import(inXml.c_str()) ; Xml_E xe_MFC = XmlI_MS ::Import(inXml.c_str()) ; tstring outCLI = inXml + _T("_CLI.svg") ; tstring outMFC = inXml + _T("_MFC.svg") ; XmlOut::Export(xe_CLI,outCLI.c_str()) ; XmlOut::Export(xe_MFC,outMFC.c_str()) ; } return nRetCode; }
—— すべてのリビルド開始: プロジェクト: L_xml_K, 構成: Debug Win32 ——
プロジェクト ‘L_xml_K’、構成 ‘Debug|Win32’ の中間出力ファイルを削除しています。
コンパイルしています…
StdAfx.cpp
コンパイルしています…
L_xml_K.cpp
c:\…\CRT_MBWC.hxx(179) : warning C4793: ‘vararg’ : 関数 ‘BOOL StPrintF(LPTSTR,size_t,LPCTSTR,…)’ 用に
ネイティブ コードの生成が発生します
c:\…\CRT_MBWC.hxx(149) : ‘StPrintF’ の宣言を確認してください。
C:\…\Xml_MS_.hxx(14) : warning C4279: ‘value’: タイプ ライブラリ ‘msxml.dll’ の識別子はキーワードです。
’rename’ 修飾子を使用してください。
C:\…\Xml_MS_.hxx(14) : warning C4279: ‘value’: タイプ ライブラリ ‘msxml.dll’ の識別子はキーワードです。…
C:\…\Xml_MS_.hxx(14) : warning C4279: ‘value’: タイプ ライブラリ ‘msxml.dll’ の識別子はキーワードです。…
C:\…\Xml_MS_.hxx(14) : warning C4279: ‘value’: タイプ ライブラリ ‘msxml.dll’ の識別子はキーワードです。…
C:\…\Xml_MS_.hxx(14) : warning C4279: ‘value’: タイプ ライブラリ ‘msxml.dll’ の識別子はキーワードです。…
C:\…\Xml_MS_.hxx(14) : warning C4279: ‘value’: タイプ ライブラリ ‘msxml.dll’ の識別子はキーワードです。…
C:\…\Xml_MS_.hxx(14) : warning C4279: ‘value’: タイプ ライブラリ ‘msxml.dll’ の識別子はキーワードです。…
リソースをコンパイルしています…
リンクしています…
マニフェストを埋め込んでいます…
L_xml_K – エラー 0、警告 8
========== すべてリビルド: 1 正常終了、0 失敗、0 スキップ ==========
C4793 は,可変個引数リストの関数のため.
コンパイラの警告 (レベル 1 および 3) C4793
C4279 は検索すると,
having MSXML warnings
Why warning C4279 happens?
C4279 は,今回のプロジェクトのみの問題となると思われる.
MSXML.dll と,System.Xml.dll を同一プロジェクトでは利用しない様にするため.
今回は,それぞれで読込み,単純に書き込む動作のデバッグのためにプロジェクトを作成した.
C++ System::Xml::XmlReader
Visual C++ を使用して、ファイルから XML データを読み取る
Netting C++ XML による構成
XmlNode メンバ
XmlNode.Attributes プロパティ
XmlNode.ChildNodes プロパティ
System::Xml を利用した読込のコードを作成していて,テスト用のコードで
—— ビルド開始: プロジェクト: L_xml_I, 構成: Debug Win32 ——
コンパイルしています…
L_xml_I.cpp
.\L_xml_I.cpp(182) : error C2039: ‘GetTempPathW’ : ‘System::IO::Path’ のメンバではありません。
c:\windows\microsoft.net\framework\v2.0.50727\mscorlib.dll : ‘System::IO::Path’ の宣言を確認してください。
.\L_xml_I.cpp(182) : error C2660: ‘GetTempPathW’ : 関数に 0 個の引数を指定できません。
L_xml_I – エラー 2、警告 0
========== ビルド: 0 正常終了、1 失敗、0 更新、0 スキップ ==========
Windows.h をインクルードしてはいけない?
使用する前?に以下を追加.
#undef GetTempPath
2020/07 https://jml.mish.work/index.php/cpp/xml.html
2019/01 C++ と STL の範囲で書き直し
リンク先に msxml.dll などを使用しない C++ で書いたコードを置いています.
2019/08 System.Xml.dll と msxml.dll を使用したコードへのリンクを追加
xml_base.hxx
Str_CLI.hxx
Xml_CLI.hxx
Xml_MS_.hxx
Xml_In.hxx
tlbimp
今度は「COM 相互運用機能」ってやつ.
Tlbimp.exe を利用して,AsFile.tlb を ISFile.dll として出力.
SDK コマンドプロンプトを開き,~\ReleaseU のフォルダに移動.
tlbimp AsFile.tlb ISFile.dll
C# フォームアプリケーションを作成して,ボタンを配置.
参照の追加で,iSFile.dll を追加.
using iSFile; を追加.
private void button1_Click(object sender,EventArgs e) {
iSFile.SearchF srchF = new iSFile.SearchF() ;
string selFile = srchF.BrowseFile(“%Temp%\\”,””) ;
MessageBox.Show(selFile) ;
}
同様の動作の vbs での呼び出しは,
dim oFSch : set oFSch = CreateObject(“AsFile.SearchF”)
selFile = oFSch.BrowseFile(“%Temp%\”,””) ;
MsgBox x
以前聞いた時には,もっと面倒なイメージがあったがそれ程でもない.
ただ COM の部分が確定していない(平行してコードを書いている)時は面倒なのかも.
同様に AsHVR.exe をやってみたら,実行時エラー.
型 ‘AsHVR.AsHVRClass’ の COM オブジェクトをインターフェイス型 ‘AsHVR.IAsHVR’ にキャストできません。
IID ‘{1625D8E7-B67B-4592-878F-ECFAD1227734}’ が指定されたインターフェイスの COM コンポーネント上での QueryInterface 呼び出しのときに次のエラーが発生したため、この操作に失敗しました:
インターフェイスがサポートされていません (HRESULT からの例外: 0x80004002 (E_NOINTERFACE))。
これが面倒だったのかも?
他にも,T54W7U64 環境で,DevXP\~\CSCallL\bin\Debug\CSCallL.exe を起動して,「ボタン 1」 もエラーとなる.
これは,AsFile.dll の 64 ビット版がないことによるものと思うが,…
うまい方法がよくわからない.
2013/08/06
既存の AsHVR.exe などがうまく動作しないのは変わらないが,
VC 8 で新規に MFC ダイアログベースのプロジェクト TstComE を作成.オートメーションを有効に.
メソッド GetTmpPath を追加して実行するとうまくいった.
C++/CLI コンソール AP として作成.
// CPCallL.cpp : メイン プロジェクト ファイルです。
#include "stdafx.h"
using namespace System;
using namespace System::Windows::Forms;
int main(array<System::String ^> ^args)
{
{
iSFile::SearchF^ srchF = gcnew iSFile::SearchF();
// String^ selFile = srchF->BrowseFile("%Temp%\\","") ;
// MessageBox::Show(selFile) ;
}
{
AsHVR::AsHVR^ hmpvr = gcnew AsHVR::AsHVR();
// String^ key = hmpvr->GetKeySP();
// MessageBox::Show(key);
}
{
TstComE::TstComE^ tce = gcnew TstComE::TstComE() ;
String^ tmpFile = tce->GetTmpPath() ;
MessageBox::Show(tmpFile) ;
}
return 0;
}
今度は TstComE 以外うまく動作しない.
CLI MSDN のサンプルなど
連載! とことん VC++
第 8 回 C++/CLI を利用した相互運用 ~ネイティブ C++ から .NET の利用~
第 9 回 C++/CLI を利用した相互運用 ~.NET からのネイティブ C++ 資産の再利用~
VC++ 2010 Express などが対象となっている.
インストールなしで用意できた環境が VS 2008 だったが,特に問題なく進められた.
メニューの「プロジェクト」-「参照の追加」は,VC 2003 以降?
VC 2005 , VC 2008 では,ソリューションエクスプローラのプロジェクトの下に「参照設定」がない?
VC 2003 には存在するので.
VC 2002 では,プログラミング VisualC++.NET Vol.2 429 ページで
#using <..\Ex32a\Debug\Ex32a.dll> となっている.
さまざまな文字列型間で変換する
Visual C++ で System::String* から char* に変換する方法
System::String を wchar_t* または char* に変換する
BUG: The VC++ .NET or VC++ 2005 debugger cannot display std::string and std::wstring variables correctly
2013/08/05
C++/CLI を用いて、.NET 対応アプリケーションから MFC 対応クラスを使用する
慣れかもしれないが,ちょっと面倒に感じる.
error BC30451
ゼロから学ぶ!最新 Visual Basic をやっていて,
—— ビルド開始: プロジェクト: GetGMail, 構成: Debug Any CPU ——
C:\…\GetGMail\Form1.vb(29) : error BC30451: 名前 ‘HttpUtility’ は宣言されていません。
C:\…\GetGMail\Form1.vb(30) : error BC30451: 名前 ‘HttpUtility’ は宣言されていません。
C:\…\GetGMail\Form1.vb(112) : error BC30451: 名前 ‘HttpUtility’ は宣言されていません。
========== ビルド: 0 正常終了または最新の状態、1 失敗、0 スキップ ==========
検索すると,「参照の追加」で System.Web を追加する必要があるとのこと.
MetaFile と MemoryDC
ODMMeta.cxx , ODrawDcM.hxx
pDC->IntersectClipRect(imgRect) ;
MetaFile mf ;
mf.SetFileName(imgN) ;
// mf.Draw(pDC,imgRect) ;
{
MemoryDC memDC ;
CRect mRect(CPoint(0,0),imgRect.Size()) ;
memDC.Init(CRect(mRect).Size()) ;
{
int colIndex = COLOR_3DFACE ;
COLORREF clrC = ::GetSysColor(colIndex) ;
CDC* mdc = memDC.GetMemoryDC() ;
CRect clrR = mRect ;
mdc->FillSolidRect(clrR,clrC) ;
mf.Draw(mdc,mRect) ;
}
memDC.Draw(pDC,imgRect) ;
memDC.Term() ;
}
ZipFold と WinXP での zip
zae などの様に,zip 内のファイル名に 5c などの文字を含まない様にしている場合は OK .
つまり,zip のファイル名として 5c が含まれていても問題ない?
→ ZipFold が MBCS のためか? 単なるバグか?
→ CharFile.hxx GetFileAttribute の “\” 削除部分のバグ.
上は GetFileAttribute のバグが原因.
Shell を使用した zip クラスの動作では,5c が含まれていてもそれなりに動作する.
UNICODE 文字はうまくなさそう.
あるフォルダ以下の圧縮で,フォルダ名が 5c 文字で終わっている場合,
MFC 6 MBCS では,CFileFind::GetFilePath の影響を受ける.
::FolderF_EnumFiles 以下の部分で,新しく定義した iFileFind を使用する様に変更.
VC 7 で error C2664 std::vector
VC 6 では通っていたが,VC 7 でエラーとなってそのままだったコード.
std::vector <void*> voidPtrs(1024,NULL) ;
c:\Program Files\Microsoft Visual Studio .NET\Vc7\include\vector(124) : error C2664:
‘std::vector >::_Construct_n’ : 2 番目の引数を ‘int’ から ‘void *const & ‘ に変換できません。
理由: ‘int’ から ‘void *const ‘ へは変換できません。
整数型からポインタ型への変換には reinterpret_cast、C スタイル キャストまたは関数スタイル キャストが必要です。
c:\Program Files\Microsoft Visual Studio .NET\Vc7\include\vector(109) :
コンパイルされたクラスのテンプレートのインスタンス化 ‘void std::vector<_Ty,_Ax>::_Construct(_Iter,int,std::_Int_iterator_tag)’ の参照を確認してください
with
[
_Ty=void *,
_Ax=std::allocator,
_Iter=int
]
c:\~\~.cpp(206) : コンパイルされたクラスのテンプレートのインスタンス化
‘std::vector<_Ty,_Ax>::vector(_Iter,int)’ の参照を確認してください
with
[
_Ty=void *,
_Ax=std::allocator,
_Iter=int
]
(void*) とすることで通るみたい.
std::vector <void*> voidPtrs(1024,(void*)NULL) ;
MFC と STL – 2
Xml_E で,MFC を使用しない様に変更中.
XML のデータを用意して,以下の様に単純に 100 個の配列にコピーする時間を計測しようとした.
ElapseTick et ;
CArray xmlAry ; // std::vector xmlAry ;
for (int index=0 ; index<100 ; index++) {
xmlAry.Add(Xml_Data) ; // xmlAry.push_back(Xml_Data) ;
}
CString etStr = ::ToString(et.GetElapse()/1000.0) ;
m_CtrlResult.SetWindowText(etStr) ;
データによっては期待した結果(MFC 版と同等またはそれより高速)が出たが,
この SVG を使用してメモリが少ない環境では極端に遅くなってしまった.
そこで,それぞれのサイズを調べてみた.
VC 6 | VC 7 | VC 8 | VC 9 | VC 10 | VC 8 Debug | VC 9 Debug | VC 10 Debug | VC 8 x64 | VC 9 x64 | VC 10 x64 | VC 9 x64 Debug | VC10 x64 Debug | Xcode 64 Debug | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
CString | 4 | 4 | 4 | 4 | 4 | 4 | 4 | 4 | 8 | 8 | 8 | 8 | 8 | |
CArray | 20 | 20 | 20 | 20 | 20 | 20 | 20 | 20 | 40 | 40 | 40 | 40 | 40 | |
tstring | 16 | 28 | 28 | 28 | 28 | 32 | 32 | 32 | 40 | 40 | 40 | 48 | 48 | 8 |
vector | 16 | 16 | 16 | 24 | 16 | 20 | 20 | 20 | 32 | 48 | 32 | 40 | 40 | 24 |
Xml_E | 68 | 92 | 92 | 108 | 92 | 108 | 108 | 108 | 152 | 184 | 152 | 184 | 184 | 72 |
tstring は,std::string または std::wstring .
vector は, <int> のサイズ.sizeof (std::vector<bool>) は vector<int> などより大きくなることがあるみたい.
Xml_E の MFC 版のデータメンバは,
CString Name , CString Text , CArray<Xml_Attribute,Xml_Attribute> Attribute , CArray<Xml_E,Xml_E> Child .
STL 版は tstring と std::vector に置換えた.
MFC Xml_Attribute | 12 | 4 + 4*2 |
MFC Xml_E | 52 | 4 + 4*2 + 20*2 |
STL Xml_Attribute | 36 | 4 + 16*2 |
STL Xml_E | 68 | 4 + 16*2 + 16*2 |
2013/04/22
SVG の全要素数は 5,557 ,属性は 19,103 .MFC 版では 518,200 ,STL 版では 1,065,584 となる.
つまり 50 M ~ 100 M 位が一時的に必要となってしまっていた(200 個にした時もあり).
ループ部分を 2 重ループとして,内側を 10 で 10 個の配列が必要となる様に改良.
時間を計測すると環境にもよるがほぼ同等の結果が得られた,
T5400 では MFC 6 秒と STL 3 秒.
DImage の利用
Shell Extension を利用した画像表示.ダイアログにファイルをドロップすると表示する様に.
1. CStatic を用意.ピクチャコントロールを配置して ClassWizard で変数を追加.
2. DImageS の領域を確保.通常はヘッダに.
3. OnDropFiles で
// CString dropFile = …. ;
ImageS.SetFileName(dropFile) ;
ImageS.Draw(&m_Image) ;
{
m_Image.ShowWindow(SW_HIDE) ;
m_Image.ShowWindow(SW_SHOW) ;
}
// …
4. OnPaint で
ImageS.Draw(&m_Image) ;
DImage では,ImageDMF が追加される.
DImage.zip
::SetCursor
使い方がわからなかったので,
最初,こんな感じにしたら,SetCursor 直後は変更されるが保持されない.
void CVEyeCSView::OnVEyeDrag()
{
VEyeChgView::OnVEye() ;
if (GetEyeChg().CanMouseEyeChange()) {
::SetCursor(m_DragEye) ;
}
else {
::SetCursor(NULL) ;
}
}
SetCursor 直後と言ってもデバッガでブレイクしている状態でないと確認はできない.
CWaitCursor と似た様な動作となる.
やりたかったのは,
BOOL CVEyeCSView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
if (nHitTest == HTCLIENT) {
if (GetEyeChg().CanMouseEyeChange()) {
::SetCursor(m_DragEye) ;
return TRUE ;
}
}
return VEyeChgView::OnSetCursor(pWnd, nHitTest, message);
}
The MFC Anser Book より
MFC と STL
MFC | STL |
---|---|
CString::Right など | string::substr |
LPCTSTR | string::c_str |
LPTSTR CString::GetBuffer() | - |
CString::ReverseFind() | string::rfind |
- | string::find_last_not_of |
Xcode で,#include “..\Test\Test.h” は通らない?
バックスラッシュではなく通常のスラッシュ ‘/’ とすれば OK (VC 6 でも通る).
2013/03/04
CString::GetBuffer() にあたる部分を,string::begin() とすると VC 6 では通る(たまたま通っているだけ).
#ifdef _MBCS
{
// tstring tmpStr = str + _T(“”) ;
// _tcsrev(tmpStr.begin()) ;
std::vector tmpStr ;
tmpStr.resize(str.length()+1) ;
_tcscpy(&tmpStr[0],str.c_str()) ;
_tcsrev(&tmpStr[0]) ;
// ….
}
#endif
昨日立ち読みした方法に改良.確かこんなんだったと思う.
2013/03/07
VC 7 でコンパイルすると,
c:\…\Test.cpp(45) : error C2664: ‘_tcsrev’ :
1 番目の引数を ‘std::basic_string::iterator’ から ‘char *’ に変換できません。
SMT-i9100 入手
SMT-i9100 が手に入った.
使用目的にもよるが,大きさはちょうどいい感じ.
2013/01/24 追記
幾つかの 3D データのビューアをインストールした.
PC から Google Play にアクセスして,探してインストールするのが簡単と思われる.
時間が経ったのでちょっと覚えてないが,Google アカウントの紐付けをデバイスと行う必要があった?
Google ドライブ上の 3D ファイルを表示する方法がわからない.
メール添付の 3D データも,開こうとするとアプリケーションエラーに.
AP を起動して,AP 付属のファイルや一部 AP で /sdcard/Download/ 以下のファイルは開ける.