ホーム » VC (ページ 5)
「VC」カテゴリーアーカイブ
enc_temp_folder
プロジェクトのソースをバックアップしていると,見慣れないフォルダ enc_temp_folder が…
その中には,先日編集した共通のソース combi_f.hpp が存在している.
ソースの中身は正規のものと比べると少し古い.
「enc_temp_folder」で検索すると,VS がクラッシュした時に生成されることがあるみたい.
確かに先日クラッシュした記憶がある.
が,その時バックアップが存在していると言う様なメッセージは気づかなかった.
原因はわかったので,削除することに.
VC プロファイラが…
先日使った VC のプロファイラがうまく動作しなくなった?
動作としては開始するが,結果が取れない.
「CPU 使用率」で,実行中のグラフは表示されている.
実行終了後,下の部分の関数名などが表示される所のデータがうまく生成されない?
次の様にやってもうまくいかない.
MSDN クイック スタート: Visual Studio の CPU 使用率データの分析 (C++)
「手順 2: CPU 使用率データの分析」のデータが取れない.
設定なども確認したが,特に影響しそうな所はわからない.
PC を再起動してもダメ.
何で?
ここに入っている VS 2008 は Team System なので,プロファイラが何とか動くみたい.
結果が表示されるまで時間がかかるのと,ボトルネックを見つけるのに使い勝手があまり良くなさそう.
もう少しあたりを付けて,単体テスト用のコードを書いて調べた方が効率が良さそう.
VC 2008 でやってみた.
VC 2015 などと比べると,生成までの時間がかかる.その後の操作も面倒.
更に出来上がっていた vsp が,193 GB .
先ず簡単に変更できるコード.
template <class V3> long V3_Search (const std::vector<V3>& pnts,const V3& pos) { for (size_t index=0 ; index<pnts.size() ; index++) { V3 pnt = pnts[index] ; if (pnt == pos) { return long(index) ; } } return -1 ; }
pnt の変数を使わず,直接比較するコードに.VC 6 でビルドして実行.
最近のコンパイラはうまく最適化してくれるので,VC 8 などでは効果がなかった(最初から速い).
ここでの検索で一致するデータは,比較的後ろの方に存在することが多いので,後ろから検索する様に変更.
// for (size_t index=0 ; index<pnts.size() ; index++)
for (long index=long(pnts.size())-1 ; index>=0 ; index--)
2021/04/12
更にコードを変更.
この関数は,呼び元との多重ループとなることがあるのと,検索して見つからないことも多いので,検索最大数を指定可能に.
template <class V3> long V3_Search_ (const std::vector<V3>& pnts,const V3& pos,const size_t max=-1) { size_t count = 0 ; for (long index=long(pnts.size())-1 ; index>=0 && count<max ; index-- , count++) { if (pnts[index] == pos) { return long(index) ; } } return -1 ; }
最大数を 1000 として,処理速度の許容範囲にはなった.
出来上がったデータとして問題ないかの検証はこれから.
検索して一致するデータは,最後と最初に存在することが多いので,その判断部分を変更.
template <class V3> long V3_Search_ (const std::vector<V3>& pnts,const V3& pos,const size_t max=-1) { for (size_t index=0 ; index<pnts.size() /*&& index<max*/ ; index++) { if (pnts[index] == pos) { return long(index) ; } size_t index_l = pnts.size()-index-1 ; if (index>=index_l) { break ; } if (pnts[index_l] == pos) { return long(index_l) ; } } return -1 ; }
20% 程度の効果.但し VC 8 でビルドしたものは遅くなってしまった.
2021/04/14
やはり,頂点などの検索のループで最大数を指定すると,得られる結果が異なる.
そのため,最大数を指定するのは限定的とする.今回は STL 読込み で 10000 に.
スタティック ライブラリで MFC …
「共有 DLL で MFC を使う」にしていたプロジェクトを「スタティック ライブラリで MFC を使用する」に変更.
ビルドして実行すると起動時エラーに.
VC 6 から順にあげてきたプロジェクトで,設定がうまく引き継がれていない.
個々のソースなどは変更した が,それだけでは足りないみたい.
プロジェクトの設定で「リソース」の「プリプロセッサの定義」に _AFXDLL が定義されてしまっている.
「<親またはプロジェクトの既定値から継承>」に変更してうまく動作する様になった.
MDI exe が動作しない?
Win10 Insider Preview 21H1 環境で,幾つかの exe がうまく動作しない.
VC 8 でビルドした exe は OK .VC 10 以降は NG のものがある.
SDI exe は大丈夫そうで,MDI exe はすべてではないが NG のものが多い.
タイミングとしては,3D データを読み込んだ後,ウィンドウに表示する前.
2021/07/12
一度「開く」ダイアログを表示するとその後はうまく動作する.
SDI exe であっても,VC 14 MFC スタティックだとうまくない?
これはプロジェクトの設定がまずかったためで,別の記事に.
2021/04/01
ちょっとわからないので,リモートデバッグの環境を作成することに.
MSDN Visual Studio での C++ プロジェクトのリモート デバッグ
リモートツールをダウンロードして,インストール.「スタート」から「Remote Debugger」を起動.
リモート側で exe を実行して,ホスト側で「アタッチ」.
2021/04/02
原因は,CRecentFileList::Add を通った時 ::CoInitinalize が呼び出されていないため.
どうも MFC 10 から?変わったみたい.
MS C++ executable just started failing
MFC application crashing in ProcessShellCommand() when file to open specified on command line
それでも,なぜ環境によっては表面化しないのか?
CRecentFileList::Add で Win7 以降の「ジャンプリスト」に登録(::SHAddToRecentDocs )する様になった.
Win10 20H2 でも現象は発生した.2004 では問題ない.
対応としては InitInstance の最初に以下を追加.
// OLE ライブラリを初期化します。
if (!AfxOleInit()) {
AfxMessageBox(_T("OLE の初期化に失敗しました。")) ;
return FALSE ;
}
2021/04/06
2016/夏頃の Win10 で,その様になるものが存在したみたい.
その頃は T90Chi + VC 2015 + i3DV でやっていたと思うが,気づかなかった?
VC コンソール AP にリソースの追加
先日作成したコンソール AP に,バージョン情報などを埋め込みたいと思い調べてみた.
検索すると次の所があった.
MSDN リソースを作成する (C++)
「Win32 コンソール アプリケーション」を「空のプロジェクト」として作成.
コードは,個人的な雛型 をコピーしてプロジェクトに登録.
#include <clocale> #include <iostream> #include "i_define.hxx" int _tmain(int argc, TCHAR* argv[]) { _tsetlocale(LC_ALL, _T("")); { std::tout << _T("hello") << std::endl; } return 0; }
「ソリューション エクスプローラー」の「プロジェクト」を「右クリック」-「追加」-「新しい項目」.
「リソース ファイル (.rc)」を選択,ファイル名を指定して「追加」.
「リソース ビュー」に切り替わるので,ツリーの「~.rc」の所を「右クリック」して「リソースの追加」.
必要に応じてアイコンなども追加.
ビルドすると exe に付加されている.
2022/08/01
バージョンリソースの読込み
FVersion.hxx
C2084: 既に本体を持っています
共通のコードを hxx にまとめてビルドすると…
------ ビルド開始: プロジェクト: G3toM, 構成: Debug Win32 ------ C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Common7\IDE\VC\VCTargets\Platforms\Win32\PlatformToolsets\v141_xp\Toolset.targets(39,5): warning MSB8051: Windows XP をターゲットとするサポートは非推奨であり、Visual Studio の将来のリリースで提供されなくなります。詳細については、https://go.microsoft.com/fwlink/?linkid=2023588 をご覧ください。 MainFrm.cpp t:\develop\_.src\__win\c_fbx_to.hxx(23): error C2084: 関数 'bool exec_FBXtoG3(c_tstring &)' は既に本体を持っています。 t:\develop\_.src\__win\c_fbx_to.hxx(22): note: 'exec_FBXtoG3' の以前の定義を確認してください t:\develop\_.src\__win\c_fbx_to.hxx(61): error C2084: 関数 'tstring call_fbx_to_ig3(c_tstring &)' は既に本体を持っています。 t:\develop\_.src\__win\c_fbx_to.hxx(60): note: 'call_fbx_to_ig3' の以前の定義を確認してください t:\develop\_.src\__win\c_fbx_to.hxx(66): error C2065: 'exec_FBXtoG3': 定義されていない識別子です。 t:\develop\_.src\__win\c_fbx_to.hxx(74): error C2065: 'exec_FBXtoG3': 定義されていない識別子です。 \\z170s0\e_temp\test.prj\test\vc_test\tomb\g3tom\mainfrm.cpp(276): error C2065: 'call_fbx_to_ig3': 定義されていない識別子です。 \\z170s0\e_temp\test.prj\test\vc_test\tomb\g3tom\mainfrm.cpp(276): error C2440: '初期化中': 'tstring (__cdecl *)(c_tstring &)' から 'std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t>>' に変換できません。 \\z170s0\e_temp\test.prj\test\vc_test\tomb\g3tom\mainfrm.cpp(276): note: コンストラクターはソース型を持てません、またはコンストラクターのオーバーロードの解決があいまいです。 プロジェクト "G3toM141.vcxproj" のビルドが終了しました -- 失敗。 ========== ビルド: 0 正常終了、1 失敗、1 更新不要、0 スキップ ==========
「inline にしているのに…」と思ったが,
#pragma once がないため複数回読み込まれていたので,追加して対応.
// *******************************************************************************
// Name : c_fbx_to.hxx
// ...
// *******************************************************************************
#pragma once
#include "W_mutex.hxx"
// ...
inline bool exec_FBXtoG3 (c_tstring& g3d_path)
{
// ...
return true ;
}
C2679 右オペランドを扱う演算子…
あるプロジェクトに デバッグライト を追加してビルドすると
------ ビルド開始: プロジェクト:T_cmb_f, 構成:Release Win32 ------ T_cmb_f.cpp T_cmb_f.cpp(32): error C2679: 二項演算子 '<<': 型 'tstring' の右オペランドを扱う演算子が見つかりません (または変換できません)。 C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\ostream(495): note: 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(std::basic_streambuf<char,std::char_traits<char>> *)' の可能性があります C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\ostream(475): note: または 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(const void *)' C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\ostream(455): note: または 'std::basic_ostream<char,std::char_traits<char>> &std::basic_ostream<char,std::char_traits<char>>::operator <<(long double)'
最近の VC はエラーの原因以外の情報がいっぱい表示されることがあるのでちょっとわかり難い.
「Unicode 文字セットを使用する」になっているのに std::cerr としていたため.
std::terr とすれば OK .
または,std::wcerr .
MBCS_Support_Deprecated_In_MFC
最初 VC 6 で作成したプロジェクト.VC 8 までは順にあげてあった.これをさらに VC 14.x まであげたもの.
その中の一部のプロジェクトを「マルチ バイト文字セットを使用する」に変更してビルドすると,
1>------ ビルド開始: プロジェクト:TEDHPro4, 構成:Debug Win32 ------ 1> StdAfx.cpp 1>c:\program files (x86)\microsoft visual studio 14.0\vc\atlmfc\include\afx.h(38): warning C4996: 'MBCS_Support_Deprecated_In_MFC': MBCS support in MFC is deprecated and may be removed in a future version of MFC. 1> c:\program files (x86)\microsoft visual studio 14.0\vc\atlmfc\include\afx.h(33): note: 'MBCS_Support_Deprecated_In_MFC' の宣言を確認してください 1> _WIN32_WINNT not defined. Defaulting to _WIN32_WINNT_MAXVER (see WinSDKVer.h) 1> TEDHPro4.cpp 1> TEDHProD.cpp 1> コードを生成中... 1>StdAfx.obj : warning LNK4075: /EDITANDCONTINUE は /OPT:LBR の指定によって無視されます。 1> TEDH4140.vcxproj -> c:\Temp\EDHProM\TEDHPro4\Debug.140\TEDHPro4.exe 1> TEDH4140.vcxproj -> c:\Temp\EDHProM\TEDHPro4\Debug.140\TEDHPro4.pdb (Full PDB) ========== ビルド: 1 正常終了、0 失敗、4 更新不要、0 スキップ ==========
今回のプロジェクトは,dll の単体テストのためのものなのでこのまま(warning が出る状態)とする.
これを回避するには「文字セット」を「Unicode 文字セットを使用する」にすること.
どうしても warning C4996 を消したいのではあれば,StdAfx.h で afx*.h のインクルードの前に NO_WARN_MBCS_MFC_DEPRECATION を定義すれば良い.
#define NO_WARN_MBCS_MFC_DEPRECATION
Win 環境で 2 重起動の禁止
ライブラリとして提供されている部分を,他のコードと分離するためコンソール AP(変換 exe)として作成.
テスト用にそれを呼出す部分も別のコンソール AP(呼出 exe)として作成.
変換 exe は,aaa.dat を aaa.txt の様に異なる形式に変換する機能.
呼出 exe は,::ShellExecute(…,”変換.exe aaa.dat”,…) の様に呼出し aaa.txt を処理する.
データにより変換(*.dat から *.txt へ)時間は数秒から数時間.
変換できたかどうかをチェックしている部分は次の様なコード.
for (size_t index=0 ; index<1000 ; index++) { ::Sleep(100) ; if (::File_IsExist(g3d_name)) { break ; } }
データが悪いのか,ライブラリの問題なのかは不明たが,変換 exe の中でエラーになってしまうことがある.
エラーを軽減する方法はわかっているが,それでも完全ではない.
同じデータでも通る時とそうでないことがあり不安定.
そのため,変換後データが存在しない時に,変換中でなければ「変換 exe」を再起動させなければならない.
2021/03/09
ここまでの部分を単体のコードとして作成.
t_call.cpp
t_conv.cpp
T_mtex_2021_03_09.zip
これらのコードでの問題は,
* 異常終了が判断できない.
* 変換に時間がかかる時,複数回呼んでしまう.
起動しているかどうかは Mutex を使えば良さそう.
変換 exe が起動している間,::CreateMutex (…,”入力ファイル名”) で作成したものを保持する.
呼出 exe のループでは,その Mutex が存在するかチェック.
なくなった時に,出力ファイルが存在している時はループを抜ける.
出力ファイルが存在していない時は,もう一度「変換 exe」を呼出す.
今まで作成の Mutex を使用したコード.
Prevent2.hxx Prevent2.cxx
ExclusS.hxx
t_conv.cpp
bool test (const tstring& name_in_) { tstring f_name = ::Path_GetName(name_in_) ; HANDLE hMutex = ::CreateMutex(NULL,FALSE,f_name.c_str()) ; time_t now = ::time(NULL) ; if ((now % 3) == 0) { ::Sleep(3000) ; tstring name_out = name_in_ + _T(".out") ; tstring name_uni = ::Get_unique_name(name_out) ; ::File_CreateEmpty(name_uni) ; } else { ::Sleep(500) ; } ::CloseHandle(hMutex) ; return true ; }
t_call.cpp
bool t_call (c_tstring& in_name_) { tstring name_in_ = in_name_ ; { tstring f_name = ::Path_GetName(name_in_) ; HANDLE hMutex = ::CreateMutex(NULL,FALSE,f_name.c_str()) ; DWORD error = ::GetLastError() ; ::CloseHandle(hMutex) ; if (error == ERROR_ALREADY_EXISTS) { return true ; } } tstring this_exe = ::i_GetModuleFileName() ; tstring conv_exe = ::Path_AddLastSP(::Path_GetDir(this_exe)) + _T("t_conv.exe") ; name_in_ = ::QuotM_Add_Auto(name_in_) ; // ... // 変換 exe を起動 // ... return true ; }
2021/03/10 更にクラスに.W_mutex.hxx
次の様にできる.
bool test (const tstring& name_in_) { W_mutex mutex(::Path_GetName(name_in_).c_str()) ; time_t now = ::time(NULL) ; if ((now % 3) == 0) { ::Sleep(3000) ; tstring name_out = name_in_ + _T(".out") ; tstring name_uni = ::Get_unique_name(name_out) ; ::File_CreateEmpty(name_uni) ; } else { ::Sleep(500) ; } return true ; } bool t_call (c_tstring& in_name_) { tstring name_in_ = in_name_ ; { W_mutex mutex(::Path_GetName(name_in_).c_str()) ; if (mutex.Is_exist()) { return true ; } } tstring this_exe = ::i_GetModuleFileName() ; tstring conv_exe = ::Path_AddLastSP(::Path_GetDir(this_exe)) + _T("t_conv.exe") ; name_in_ = ::QuotM_Add_Auto(name_in_) ; // ... return true ; }
2021/12/01
W_mutex を利用した単体テスト用コード
VC 14 デバッグ MFC にステップイン
VC 2015 で MFC を使用した SDI.exe をデバッグしていると,MFC のコードにステップインできない?
入っている他の VC で試すと VC 2013 まではうまく機能している.
検索しても,これはという内容には引っ掛からなかった?
アプリケーションクラスの CG3toMApp::InitInstance() を抜ける時,そのままステップ実行していると…
「Microsoft Symbol Servers」にチェックを付けて「読み込み」.
MFC ソース内のデバッグができる様になった.
設定としては「ツール」-「オプション」の中の「デバッグ」-「シンボル」.
2022/02
%TEMP% では消えてしまうので,シンボルキャッシュの場所を変更している.
VC フォールバック 設定
https://itl.mish.work/Iwao/Doc/other/vs/
https://jml.mish.work/index.php/cpp/vs-install.html
VC 12 LNK1104 , VC 14.2 LNK2019
VC 6 のプロジェクトを順に更新して,…
------ ビルド開始: プロジェクト:BChgN, 構成:Debug Win32 ------ BChgN.obj : warning LNK4075: /EDITANDCONTINUE は /OPT:LBR の指定によって無視されます。 LINK : fatal error LNK1104: ファイル 'mfc120d.lib' を開くことができません。 ------ ビルド開始: プロジェクト:G3_CLS, 構成:Release Win32 ------ LINK : fatal error LNK1104: ファイル 'mfc120.lib' を開くことができません。 ------ ビルド開始: プロジェクト:G3_CLS, 構成:Debug Win32 ------ G3_CLS.obj : warning LNK4075: /EDITANDCONTINUE は /OPT:LBR の指定によって無視されます。 LINK : fatal error LNK1104: ファイル 'mfc120d.lib' を開くことができません。 ------ ビルド開始: プロジェクト:G3_toM, 構成:Debug Win32 ------ ComPrj01.obj : warning LNK4075: /EDITANDCONTINUE は /OPT:LBR の指定によって無視されます。 LINK : fatal error LNK1104: ファイル 'mfc120d.lib' を開くことができません。 ------ ビルド開始: プロジェクト:ig3_toM, 構成:Release Win32 ------ LINK : fatal error LNK1104: ファイル 'mfc120.lib' を開くことができません。 ------ ビルド開始: プロジェクト:ig3_toM, 構成:Debug Win32 ------ ComPrj01.obj : warning LNK4075: /EDITANDCONTINUE は /OPT:LBR の指定によって無視されます。 LINK : fatal error LNK1104: ファイル 'mfc120d.lib' を開くことができません。 ========== ビルド: 0 正常終了、6 失敗、4 更新不要、0 スキップ ==========
ビルドを開始しました... ------ ビルド開始: プロジェクト: BChgN, 構成: Debug Win32 ------ BChgN.obj : warning LNK4075: /EDITANDCONTINUE は /INCREMENTAL:NO の指定によって無視されます。 msvcrtd.lib(exe_wwinmain.obj) : error LNK2019: 未解決の外部シンボル _wWinMain@16 が関数 "int __cdecl invoke_main(void)" (?invoke_main@@YAHXZ) で参照されました c:\Temp\TestMBL\BChgN\Debug.142\BChgN.exe : fatal error LNK1120: 1 件の未解決の外部参照 プロジェクト "BChg142.vcxproj" のビルドが終了しました -- 失敗。 ========== ビルド: 0 正常終了、1 失敗、9 更新不要、0 スキップ ==========
BChgN は SDI.exe .それ以外は MFC を使用したコンソール AP .
うまくビルドできる vcxproj と比べると,ソースのプリプロセッサの定義が異なる.
それならと思い,VC の「ソリューション エクスプローラ」で,ソースを一度プロジェクトから外して,再度追加.
うまくビルドできる様になった.
vcxproj をエディタで開き直すと,<PreprocessorDefinitions Condition> がない.
<ItemGroup> <ClCompile Include="ComPrj01.cpp" /> <ClCompile Include="ig3_toM.cpp" /> </ItemGroup>
StdAfx.cpp 以外はファイル名のみで良さそう.
他のプロジェクトは,エディタで削除して対応.
2020/01/25
今度は,MFC を使用していないコンソール AP .
VC の設定で「それぞれのソースのプロパティページ」-「構成プロパティ」-「C/C++」-「プリプロセッサ」-「プリプロセッサの定義」をブランクにしてみたが…
コンパイルすると _UNICODE などが定義されない.
「<親またはプロジェクトの既定値から継承>」にすることで,意図した設定になった.
2024/07/04
以前は VC 7 などを通していたが,最近は VC 8 以降のみにしている.
VC6 プロジェクトの移行
VC6 から VC2019 への移行
こうすることで,プリプロセッサの定義がうまくない現象はなくなった様に思う..
VC でのプロファイル
VC 6 の頃はよく使っていたが…
VC 12 では何故かうまく動かなかった.
VC 14 で簡単に動作を確認すると,前より使い易くなっている.
メニューの「分析」-「パフォーマンス プロファイラー」.
「CPU 使用率」にチェックを付けて「開始」.
プロファイル用にビルドされて exe が起動する.
テストする操作を行い exe を終了させる.
暫くすると結果が表示される(この情報の見方はよくわからず).
CPU のグラフの下の「詳細なレポートを作成します…」を「クリック」.
上の方のドロップダウンから「関数」を選択.
表示された関数名のリストから関数をダブルクリック(ここでは CF_GetOuterLine ).
ちょっと意外だったが,Vd3A の代入に時間がかかっている.
2020/12/23
Vd3A の代入ではなく参照にコードを変更.
テストする exe も,もう少し機能を単純化したものを使用.
データにもよるが,該当部分の時間が半分位になった.
更にループ内の Vd3 も参照にしてみたが,こちらは効果なし.
typedef Vector3<double> Vd3 ; // 3D 座標 ( double の x , y , z ) typedef std::vector<Vd3> Vd3A ; // 3D 座標の配列
Vd3A は可変長で,メモリの確保と解放が伴うためと思われる.
* デバッグ版のため実際のコード(計測した Release 版)とは異なると思う.
SetConsoleCtrlHandler
コンソール AP で,キー入力による中断ができないかと…
やりたいことは,時間がかかるコンソール AP で,その途中までの計算結果を保存すること.
「コンソールアプリ 中断」で検索すると ::SetConsoleCtrlHandler を使えば良さそう.
MSDN を「PHANDLER_ROUTINE」で検索.次のサンプルが見つかった.
そのタイトル「Registering a Control Handler Function」で検索.
コントロール ハンドラー関数の登録
https://www.installsetupconfig.com/win32programming/
https://www.installsetupconfig.com/win32programming/winconsolecharapplication8index.html
#pragma message ( … (value) )
FBX SDK を使用したプロジェクトで,コンパイル時 FBX SDK のバージョンを表示したくなった.
FBX 2013.3 SDK 位からは FBXSDK_VERSION_STRING が使える.
#ifdef FBXSDK_VERSION_STRING #pragma message ("FBXSDK_VERSION " FBXSDK_VERSION_STRING) #endif
それより古い場合に,コンパイルオプションで FS_VER=201100 などと指定する様にした.
考え方や動作は意図した通りになったが,この FS_VER を表示できないものかと…
検索すると VC では _CRT_STRINGIZE が使えるとあった.
コンパイル時に#defineの値を表示するにはどうすればよいですか?
#ifdef FS_VER #pragma message ("FS_VER " _CRT_STRINGIZE(FS_VER)) #endif
_CRT_STRINGIZE は …\VC\include\crtdefs.h や …\VC\include\vcruntime.h に定義されている.
古い VC などでも使える様に…
#ifndef __CRT_STRINGIZE #define __CRT_STRINGIZE(Value) #Value #endif #ifndef _CRT_STRINGIZE #define _CRT_STRINGIZE(Value) __CRT_STRINGIZE(Value) #endif
MFC DLL error C2371 cerr
FBX SDK を使用したテストプロジェクト.
以前「MFC を使用する」になっていたもの.
関連するコードを変更して「MFC を使用しない」に書き換え.
そのままのコードを「MFC を使用する」に戻すと,…
--------------------構成: T_FBX - Win32 DebugM-------------------- コンパイル中... T_FBX.cpp c:\program files\microsoft visual studio\vc98\mfc\include\afx.h(1941) : error C2371: 'cerr' : 再定義されています。異なる基本型です。 c:\program files\microsoft visual studio\vc98\include\iostream(19) : 'cerr' の宣言を確認してください。 nothing FS_VER VC 6 200508 cl.exe の実行エラー T_FBX.exe - エラー 1、警告 0
前に変更しているが,元に戻す方が良いのか?
そもそもこの部分を削除した方が良いか?
https://dev.mish.work/wordpress/2020/04/17/rc1047-c2679/
今回は i_define.hxx から次の部分を削除.
#ifdef _MSC_VER #ifdef _MFC_VER #else #ifndef afxDump #define afxDump std::terr #endif #endif #endif
必要があれば i_debug.hxx に追加する.
ドライブ名からリモート名に
ネットワークドライブ名から UNC での表現に変換するコード.
#include <clocale> #include "i_trace.hxx" //#include <winnetwk.h> #pragma comment (lib,"mpr.lib") tstring W_get_remote_name (LPCTSTR path_) { tstring dpath = path_ ; if (dpath.size() < 2) { return dpath ; } tstring drive = dpath.substr(0,2) ; tstring _path = dpath.substr(2) ; tstring remote_path ; if (drive.length() == 2) { if (drive[1] == _T(':')) { u_16 d_t = ::GetDriveType(drive.c_str()) ; if (d_t == DRIVE_REMOTE) { DWORD buf_size = MAX_PATH ; tstring remote_name ; remote_name.resize(buf_size+1) ; ::WNetGetConnection(drive.c_str(),&remote_name[0],&buf_size) ; if (!remote_name.empty()) { remote_path = remote_name.c_str() + _path ; } } } } if (remote_path.empty()) { return dpath ; } return remote_path ; } bool Test (void) { for (long index=0 ; index<26 ; index++) { tstring drv ; drv += TCHAR(_T('A')+index) ; drv += _T(":\\") ; // if (index%2 == 0) { u_16 d_t = ::GetDriveType(drv.c_str()) ; if (d_t == DRIVE_REMOTE) { drv += _T("*.*") ; v_tstring files = ::EnumFiles(drv.c_str()) ; if (files.size() > 0) { drv = files[0] ; } } } drv += _T(" ") ; tstring info = drv.substr(0,20) + _T("\t") + W_get_remote_name(drv.c_str()) ; { std::tout << info << std::endl ; } } return true ; } int _tmain (int argc,TCHAR* argv[]) { _tsetlocale(LC_ALL,_T("")) ; { ::Test() ; } return 0 ; }
「 net use 」とコマンド入力することで似た様なことを確認できる.
管理者で起動した PowerShell の Get-SmbConnection で SMB のバージョンを確認できる.
ファイル共有で使われている SMB のバージョンを見る
std::vector のコピーで実行時エラー
std::vector のデータ vf3a をコピーしようとして実行時エラー.
--------------------------- Microsoft Visual C++ Debug Library --------------------------- Debug Assertion Failed! Program: c:\Temp\Test\T_gonsa\T_cmb_f\debug.080\T_cmb_f.exe File: c:\program files (x86)\microsoft visual studio 8\vc\include\vector Line: 741 Expression: vector subscript out of range 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) ---------------------------
原因は vf3a のサイズが 0 .
vf3a.size() が 0 より大きい時のみコピーする様に変更しなければならない.
inline v_u__8 To_v_u__8 (const Vf3A& vf3a)
{
v_u__8 data ;
{
size_t vCount = vf3a.size() ;
u_16 vf3_size = u_16(sizeof(float)*3*vCount) ;
data.resize(sizeof(u_16)+vf3_size) ;
{
::MemMove(&data[0],sizeof(u_16),&vCount,sizeof(u_16)) ;
}
if (vCount > 0) {
::MemMove(&data[2],vf3_size, &vf3a[0],vf3_size) ;
}
}
return data ;
}
フォルダの更新日時の変更
今までファイルの更新日時の変更は使っていた.
https://www.vector.co.jp/soft/winnt/util/se500182.html
が,このツールでフォルダの更新日時を変更しようとするとできない.
コードは CFile::SetStatus を使用している.
CFileStatus fs ; CFile::GetStatus(file,fs) ; fs.m_mtime = newTime ; CFile::SetStatus(file,fs) ;
CFile::SetStatus の中(…\atlmfc\src\mfc\filest.cpp)を見ると ::SetFileTime を使用している.
また Linux などでも使える utime(…\crt\src\utime.c)も ::SetFileTime を使っている.
VC 6 で作成したものをデバッガで追いかけると ::CreateFile で 0xffffffff が返ってきている.
ASUSTOR NAS で試すと,特に問題なく変更できる.
Iwao@AS5202T:/volume1/home/Iwao/gcc_test/Test/t_linux/t_mtime/t_utime $ cat t_utime.cpp #include <clocale> #include "i_trace.hxx" #include "filetime.hxx" #include "itls_tmp.hxx" #include "c_which.hxx" int _tmain (int argc,TCHAR* argv[]) { _tsetlocale(LC_ALL,_T("")) ; { tstring temp_path = ::Get_i_Tools_tmp_date() ; tstring fold_path = ::Path_AddLastSP(temp_path) + ::Now_Format(_T("%H%M%S")) ; tstring file_path = ::Path_AddLastSP(temp_path) + ::Now_Format(_T("%H%M%S")) + _T(".tmp") ; { ::Folder_Create (fold_path) ; ::File_CreateEmpty(file_path) ; } { time_t f_time = ::File_GetMTime(file_path.c_str()) ; f_time-= 3600*24*7 ; ::File_SetMTime(file_path.c_str(),f_time) ; ::File_SetMTime(fold_path.c_str(),f_time) ; } { tstring cmd = tstring(cmd_ls_la) + _T(" ") + ::QuotM_Add_Auto(temp_path) ; _tsystem(cmd.c_str()) ; } } return 0 ; } Iwao@AS5202T:/volume1/home/Iwao/gcc_test/Test/t_linux/t_mtime/t_utime $ g++ t_utime.cpp -Wall Iwao@AS5202T:/volume1/home/Iwao/gcc_test/Test/t_linux/t_mtime/t_utime $ ll total 136 drwxrwxrwx 2 Iwao users 4.0K Nov 7 16:24 ./ drwxrwxrwx 3 Iwao users 4.0K Nov 7 15:32 ../ -rwxr-xr-x 1 Iwao users 122.7K Nov 7 16:24 a.out* -rwxrwxrwx 1 Iwao users 838 Nov 7 16:22 t_utime.cpp* Iwao@AS5202T:/volume1/home/Iwao/gcc_test/Test/t_linux/t_mtime/t_utime $ ./a.out total 0 drwxr-xr-x 3 Iwao users 80 Nov 7 16:24 . drwxr-xr-x 3 Iwao users 60 Nov 7 16:24 .. drwxr-xr-x 2 Iwao users 40 Oct 31 16:24 162451 -rw------- 1 Iwao users 0 Oct 31 16:24 162451.tmp Iwao@AS5202T:/volume1/home/Iwao/gcc_test/Test/t_linux/t_mtime/t_utime $
2024/01/04
フォルダの更新日時の設定
C++ 継承でのエラー C2660
元々一つのクラスとしていたが,それを分割した時のエラー対応のメモ.
bool D_Image::Draw (HDC hdc,const RECT rect) { if (GetDocPath().empty()) { return false ; } { if (::Path_GetExtLow(GetDocPath()) == _T("emf")) { return E_MetaF::Play(hdc,GetDocPath().c_str(),rect) ; } } if (HBMP == NULL && HICN == NULL) { // ... } if (HBMP != NULL) { return ::Bitmap_Draw(hdc,rect,HBMP) ; } else if (HICN != NULL) { return ::Icon_Draw (hdc,rect,HICN) ; } return false ; } bool D_Image::Draw (HWND hwnd) { if (GetDocPath().empty()) { return false ; } if (hwnd == NULL) { return false ; } RECT rect = { 0 } ; ::GetClientRect(hwnd,&rect) ; bool result = false ; { HDC hdc = ::GetDC(hwnd) ; result = Draw(hdc,rect) ; ::ReleaseDC(hwnd,hdc) ; } return result ; }
この E_MetaF::Play の部分を分離.
class D_I_E : public D_Image { public: virtual bool Draw (HDC hdc,const RECT rect) { if (GetDocPath().empty()) { return false ; } { if (::Path_GetExtLow(GetDocPath()) == _T("emf")) { return E_MetaF::Play(hdc,GetDocPath().c_str(),rect) ; } } return D_Image::Draw(hdc,rect) ; } } ;
この状態で変数の宣言を D_I_E として呼び出している所でエラー.
Sel_doc.Draw(this->GetSafeHwnd()) ; // Sel_doc.D_Image::Draw(this->GetSafeHwnd()) ;
--------------------構成: T_DImage - Win32 Debug-------------------- コンパイル中... T_DI_Dlg.cpp \\TestXP\Documents\Develop\VC_Test\Test\etc\EnhMetaF\T_DImage\T_DI_Dlg.cpp(186) : error C2660: 'Draw' : 関数が不正な 1 個の実引数をともなって呼び出されました。 cl.exe の実行エラー T_DImage.exe - エラー 1、警告 0
下の様に修飾すれば通る.
また,D_I_E の関数として次のものを用意すれば D_Image:: の様に修飾しなくても大丈夫.
virtual bool Draw (HWND hwnd) { return D_Image::Draw(hwnd) ; }
構造体の初期化
幾つかの Windows API を呼び出す所を書き換えていて,
RECT や POINT の構造体の初期化で色々と気になり少し調べたことのまとめ.
class として書く場合は,コンストラクタで初期化しているので意識しない.
struct Vector2 { // Vector2 () {} Vector2 (T v=0) : x(v), y(v) {} Vector2 (T x, T y) : x(x), y(y) {} // ... T x ; T y ; } ;
MFC を使用している時も同様.
CRect rect(0,0,0,0) ;
他の Win32 の構造体だと
MEMORYSTATUSEX memStat ; memset(&memStat,0,sizeof(MEMORYSTATUSEX)) ; memStat.dwLength= sizeof(MEMORYSTATUSEX) ; ::GlobalMemoryStatusEx(&memStat) ;
Windows では ::ZeroMemory を使っていることもあり.
#define ZeroMemory(pb,cb) memset((pb),0,(cb))
これまで RECT を 0 にする場合,次の様にも書いていた.
RECT rect = { 0,0,0,0 } ;
次の様に省略する方法もあるのは知っていたがあまり使っていない.
RECT rect = { 0 } ;
K & R 2nd の A8.7 に書かれている.
Web で検索すると ” RECT rect = { } ; ” の様な記述もあったが,これはどうかと…
構造体のコピーや戻り値は悩む所.
RECT の様な単純な構造では特に問題ないと思う.
XML などのツリー構造の場合はデータにより時間がかかるので注意が必要.
2020/10/13
次の様なコードで動作 を確認.
struct strct_c { i__8 i1 ; i_32 i4 ; i_16 i2 ; i_64 i8 ; } ; bool test_struct (void) { strct_a sa_rn ; strct_b sb_rn ; strct_c sc_rn ; strct_a sa_f0 = {1,2,3,4} ; strct_b sb_f0 = {1,2,3,4} ; strct_c sc_f0 = {1,2,3,4} ; strct_a sa__0 = {0} ; strct_b sb__0 = {0} ; strct_c sc__0 = {0} ; strct_a sa_m0 ; memset(&sa_m0,0,sizeof(sa_m0)) ; strct_b sb_m0 ; memset(&sb_m0,0,sizeof(sb_m0)) ; strct_c sc_m0 ; memset(&sc_m0,0,sizeof(sc_m0)) ; ::dump_mem(&sc_rn,sizeof(sc_rn)) ; ::dump_mem(&sc_f0,sizeof(sc_f0)) ; ::dump_mem(&sc__0,sizeof(sc__0)) ; ::dump_mem(&sc_m0,sizeof(sc_m0)) ; return true ; }