マンガでよめる痔のこと・薬のこと

いつも拝見させていただいております。

さっそくですが、質問致します。

現在、ネイティブなC++ DLLを作成しています。
これを今回、C#のアプリケーションから呼び出すことになりました。
DLL内にはクラスを作成しており、内部にXMLのデータを保持するような
クラスを作成しております。(XML操作にはMSXMLを使用しております。)

問題なのはC++アプリケーションから呼び出した時は正常に動作するのですが、C#からの呼び出しの時はC++アプリケーションから呼び出した時には発生していないエラーが検出されます。

エラー内容は
System.AccessViolationException
保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。
になります。
エラー内容からしてC++内でのメモリ操作に問題があると
思われるのですが、C++からの実行時には検出されていないので理由がわからずに困っております。
ネイティブなDLLに対してはデバッグも行えないため、手に負えません。
(現在、1行ごとにログを埋め込み、TCHAR型のnewを4byte行っている箇所で処理がストップしてしまっているようです。C++からの呼び出し時には正常に処理される箇所です。)
ネイティブなDLLに対してのデバッグ方法や似たような現象にあわれた方がいらっしゃいましたらご助力お願い致します。


・対象のDLLのクラスは_declspec(dllexport)にてエクスポートを行っています。

・C#からの呼び出し時にはネイティブなDLLのためC++/CLIで作成したプロジェクトでラッパークラスを作成してアクセスを行っています。

・C++アプリケーションからの呼び出し時はプロパティの設定でインクルードディレクトリ、LIBファイルの設定等を行って直接DLLを参照して
実行(呼び出し)しています。

このQ&Aに関連する最新のQ&A

A 回答 (2件)

C++側の出力ファイル .DLL .PDB などを C#の出力フォルダ bin\debug などに出力しておいて



C#側のプロジェクトプロパティのデバッグの『アンマネージ コードのデバッグ』にチェックを付けておく

こうしておけば C++のコードもデバッグできると思いますよ

この回答への補足

ご回答頂いた内容にてアンマネージドコードのデバッグは
可能となりました。
ですが、また厄介なことにC#からの呼び出し時にデバッグしてみても
エラーとなりません。
アンナネージドコードデバッグを無効に設定すると再度現象が発生します。
他に何か有益そうな情報がありましたらご教授願いします。

補足日時:2008/05/20 14:40
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
なるほど。設定を行うことでデバッグが可能となるとは思いませんでした。
これで少し進展があればよいのですが。。
ご助力ありがとうございます。

お礼日時:2008/05/20 01:56

デバッグビルドではなくリリースビルドにして


C++DLL側を Debug情報の生成=はい にして
デバッグしてみてはいかがでしょう

デバッグビルド時に具現化しないバグも捕まえられるかもしれません
    • good
    • 0

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Q「AccessViolationException」と出てしまい、困っています

VisualBasic2005でプログラミングしているのですが、
フォームからAccessのレポートを開こうとしたら、
「System.AccessViolationException」というメッセージが出てしまい、
レポートが表示されません。

Dim app As New Access.Application

app = New Access.ApplicationClass()
app.OpenAccessProject(Accessファイルのパス)
app.DoCmd.OpenReport("レポート", Access.AcView.acViewPreview, , "[番号]='" & txt_No.Text & "'")

どこか記述がおかしい所があるのでしょうか。ご教授よろしくお願いします。

Aベストアンサー

興味がわいたのでちょっとサンプル作成...

「じゃんぬねっと」さんのページを拝見しながら、書いたので参照リリース漏れは無いはず....
COM オブジェクトの参照カウントを解放する
http://jeanne.wankuma.com/tips/programing/releasecom.html

このサンプルはレポートを表示してから、10秒でアクセスごと終了します
そこらへんは工夫が必要ですw

普通にクリスタルレポートを使用したほうが、もうちょっとスマートにいけそうですね
あと、気になったのは
>app.OpenAccessProject(Accessファイルのパス)
と記述していますが、「Accessファイルのパス」の拡張子は"adp"ですか?
たぶん、「Accessファイルのパス」と記述しているので
app.OpenCurrentDatabase(Accessファイルのパス)
と記述しなければならないのでは?

開発環境:WindowsXP+VB2005+Access2003
※ちなみにWindowsVista+VB2005+Access2007でやったら、セキュリティがうんたらかんたら('A`)マンドクセ

Imports Microsoft.Office.Interop
Imports System.Runtime.InteropServices
Imports System.IO

Public Class Form1

  Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

    Dim acApp As Access.Application = Nothing

    Try
      acApp = New Access.Application

      Dim filePath As String = Path.Combine( _
        Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), _
        "db1.mdb")

      If (File.Exists(filePath)) Then
        acApp.OpenCurrentDatabase(filePath)
        acApp.Visible = True

        Dim doCmd As Access.DoCmd = acApp.DoCmd
        Try
          Dim reportName As String = "testReport"
          doCmd.OpenReport(reportName, Access.AcView.acViewPreview)
          System.Threading.Thread.Sleep(10 * 1000)
        Finally
          Marshal.ReleaseComObject(doCmd)
        End Try

        acApp.CloseCurrentDatabase()
      Else
        Dim message As String = String.Format("指定されたファイルは存在しません「{0}」", filePath)
        MessageBox.Show(Me, message, "IO Error", MessageBoxButtons.OK, MessageBoxIcon.Warning)
      End If
    Finally
      If Not acApp Is Nothing Then
        Try
          acApp.Quit()
        Finally
          Marshal.ReleaseComObject(acApp)
        End Try
      End If
    End Try

  End Sub

End Class

興味がわいたのでちょっとサンプル作成...

「じゃんぬねっと」さんのページを拝見しながら、書いたので参照リリース漏れは無いはず....
COM オブジェクトの参照カウントを解放する
http://jeanne.wankuma.com/tips/programing/releasecom.html

このサンプルはレポートを表示してから、10秒でアクセスごと終了します
そこらへんは工夫が必要ですw

普通にクリスタルレポートを使用したほうが、もうちょっとスマートにいけそうですね
あと、気になったのは
>app.OpenAccessProject(Accessファイルのパ...続きを読む

QC# DLL エントリ ポイントが見つかりません。

C#で作成したDLLをC#から呼出したいのですが、うまくいきません。

// トリガ
private void button2_Click(object sender, EventArgs e)
{
string ans = DLL.moji();
MessageBox.Show(ans);
}

// DLL呼出し用クラス
class DLL
{
[DllImport("LibCsharp.dll")]
public static extern string moji();
}

// DLL(LibCsharp.dll内容)
class AddClass
{
public static string moji()
{
return ("テスト");
}
}

上記で実行すると「EntryPointNotFoundException DLL 'LibCsharp.dll' の 'moji' というエントリ ポイントが見つかりません。」となります。

プロジェクトの参照設定にはLibCsharpを追加しています。
Web上で調べたのですが、解決には至っておりません。

申し訳ありませんが、よろしくお願いします。

C#で作成したDLLをC#から呼出したいのですが、うまくいきません。

// トリガ
private void button2_Click(object sender, EventArgs e)
{
string ans = DLL.moji();
MessageBox.Show(ans);
}

// DLL呼出し用クラス
class DLL
{
[DllImport("LibCsharp.dll")]
public static extern string moji();
}

// DLL(LibCsharp.dll内容)
class AddClass
{
public static string moji()
{
...続きを読む

Aベストアンサー

#1です。

私もc#で簡易な独自ライブラリを構築しようとしていたので調べてみました。
結果として参照の追加でdllを直接、指定するだけで使用可能だと分かりました。
(「参照設定」右クリック→「参照の追加」→「参照」タブ選択→DLLを選択)


まず基本的な知識としてdllには3種類あると覚えて下さい。

・レガシー(古い遺産)dll
・active-x dll
・.net dll


私はレガシーdll時代の知識しかありませんでした。
この頃のdllを使用するためには、dll本体以外に以下のファイルが必要でした。

・ヘッダファイル
・ライブラリ(lib)ファイル
・defファイル(場合による)


c#で作られたdllは[.net dll]となり、[.net freamwork]上で動作する各種の言語で使用出来るようにするため、煩わしいlibファイルやヘッダファイル等を削除する方向でdllが進化しているのだと思われます。

ネット検索をしていて見つけたのですが、[.net dll]で作成されたFTPクライアントのライブラリがありました。
(.NET用FTPクラスライブラリ (TKFP.DLL) )

どの言語で作られているのか分かりませんが、[.net dll]で作られているため、c#およびvbで使用可能のようです。
追加したdll内に含まれているクラスや関数に対してオブジェクトブラウザで概要が表示出来るようにXMLファイルで概要を記述出来るようなのですが、詳細まで調べることが出来ませんでした。
(申し訳ありません。)

#1です。

私もc#で簡易な独自ライブラリを構築しようとしていたので調べてみました。
結果として参照の追加でdllを直接、指定するだけで使用可能だと分かりました。
(「参照設定」右クリック→「参照の追加」→「参照」タブ選択→DLLを選択)


まず基本的な知識としてdllには3種類あると覚えて下さい。

・レガシー(古い遺産)dll
・active-x dll
・.net dll


私はレガシーdll時代の知識しかありませんでした。
この頃のdllを使用するためには、dll本体以外に以下のファイルが必要でした。

・...続きを読む

QVS2010C#からのDLL使用について

VS2010 C#からVC6で作成したDLLへint配列を引数として渡したい。
VC++6で作成されたDLLがあります。
ここで定義されている

int test(char*fname,int* x,int* y);

ファイルのフルパスを渡すと
返り値が関数の成否のコードを返す。
処理内で x,y
にファイルから読み込んだ値が
それぞれ上限100個としてセットして返す
といったような関数を
C#から呼び出したいのですが

1
[DllImport("dll名", EntryPoint = "test", CallingConvention = CallingConvention.Cdecl)]
public unsafe static extern int test(IntPtr fname, ref int* x,ref int* y);

2
[DllImport("dll名", EntryPoint = "test", CallingConvention = CallingConvention.Cdecl)]
public unsafe static extern int test(IntPtr fname, ref IntPtr x,ref IntPtr y);

と2種類の呼び出し方法をこころみました。


ファイルのフルパスは
IntPtr fnamePtr = Marshal.StringToHGlobalAnsi(string型ファイルフルパス);
としております。

1の場合は
int[] resX = new int[100];
int[] resY = new int[100];
fixed(int* x= resX)
fixed(int* x= resY)
として呼び出そうとすると

: エラー CS1657: '固定変数' であるため、'x' を ref または out 引数として渡せません
となり失敗してしまいます。

2
で試みた場合
int size = sizeof(int)*100;
IntPtr x = Marshal.AllocHGlobal(size);
IntPtr y = Marshal.AllocHGlobal(size);
と引き渡したところ
ビルドは通りますが
実行時に
System.AccessViolationException' のハンドルされていない例外が 発生しました。

追加情報: 保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。
となってしまいます。

どのようにすれば思惑通りの結果を得られますでしょうか。

VS2010 C#からVC6で作成したDLLへint配列を引数として渡したい。
VC++6で作成されたDLLがあります。
ここで定義されている

int test(char*fname,int* x,int* y);

ファイルのフルパスを渡すと
返り値が関数の成否のコードを返す。
処理内で x,y
にファイルから読み込んだ値が
それぞれ上限100個としてセットして返す
といったような関数を
C#から呼び出したいのですが

1
[DllImport("dll名", EntryPoint = "test", CallingConvention = CallingConvention.Cdecl)]
public unsafe static extern int test(IntP...続きを読む

Aベストアンサー

難しく考えなくても出来るようですよ

[DllImports("DLL名", CharSet=CharSet.Ansi, EntryPoint="test")]
public static extrn int test( string fname, [Out] int[] xx, [Out] int[] yy );
と宣言して

int[] x = new int[100];
int[] y = new int[100];
int res = -2;

res = test( "ファイル名", x, y );
でOKみたいですよ …

unsafeにしなくても いいみたいですし

QDLL参照時に指定されたモジュールが見つかりません。(HRESULT からの例外 0x8007007E) が発生してしまう。

C++プロジェクト(Windowsフォームアプリ)を作成し、あるサイトで公開されているDLLを実装し→コンパイル→デバッグ実行させた所、問題なく動作が確認できたのですが、
クラスライブラリで作成したC++新規プロジェクトに同じくDLLを実装し、同一ソリューション内にC#又はC++でWindowsフォームアプリを作成し、先に作成したクラスライブラリプロジェクトを参照させる形態で作成した際に、コンパイル→デバッグ実行させた所、コンパイルは通ったのですがデバッグ実行時に、DLLを参照しようとしたタイミングで
「DLL参照時に指定されたモジュールが見つかりません。(HRESULT からの例外 0x8007007E) が発生してしまう。」
というエラーが発生してしまいました。

何故Windowsフォームアプリ単体時にはDLLが参照できたのに、クラスライブラリにし複数プロジェクトにして実行するとエラーが発生してしまうのか、どなたか原因、解法等 心得ておられましたら御指南のほど宜しくお願いします。

以下 事象詳細です。
開発環境:Microsoft Visual Studio 2008
公開DLL:USB-IOを制御する目的のUSBIODLLDemo.dllというDLLです。

<成功時>
1.C++プロジェクト(Windowsフォームアプリ)新規作成
2.DLLがインストールされているフォルダから.dllファイル, .hファイル、.libファイルをコピーしプロジェクト新規作成したフォルダにコピーする
3.プロジェクトのプロパティ→構成プロパティ→リンカ→入力→追加の依存ファイル に.libファイル名を記入
4.ダウンロードの.hファイルから
__declspec(dllimport) BYTE __stdcall GetNo(void);
__declspec(dllimport) void __stdcall P1Write(BYTE newVal);
__declspec(dllimport) BYTE __stdcall P1WriteBit(BYTE Bit, BOOL Tf01);
__declspec(dllimport) BYTE __stdcall P1Read(void);
 をコピーしstdafx.h へ貼付け。
5.stdafx.hへ貼り付けた宣言がこのままではコンパイルが通らなかったため
#define BYTE unsigned char
#define BOOL bool
 を追記。
6.ダウンロードしたDLLの関数を使用した一文を実装
7.コンパイル→デバッグ実行→ 無事実行完了!

<エラー発生時> *下記事象ではC#Winフォームアプリを挙げていますがC++Winフォームアプリで試しても同じ結果になりました。
1.C++プロジェクト(クラスライブラリ)新規作成
2.DLLがインストールされているフォルダから.dllファイル, .hファイル、.libファイルをコピーしプロジェクト新規作成したフォルダにコピーする
3.プロジェクトのプロパティ→構成プロパティ→リンカ→入力→追加の依存ファイル に.libファイル名を記入
4.ダウンロードの.hファイルから
__declspec(dllimport) BYTE __stdcall GetNo(void);
__declspec(dllimport) void __stdcall P1Write(BYTE newVal);
__declspec(dllimport) BYTE __stdcall P1WriteBit(BYTE Bit, BOOL Tf01);
__declspec(dllimport) BYTE __stdcall P1Read(void);
 をコピーしStdafx.h へ貼付け。
5.Stdafx.hへ貼り付けた宣言がこのままではコンパイルが通らなかったため
#define BYTE unsigned char
#define BOOL bool
 を追記。
6.ダウンロードしたDLLの関数を使用した一文を実装(公開関数として)

7.C#プロジェクト(Windowsフォームアプリ)新規追加 *C++(Windowsフォームアプリ)でやっても同じ結果になりました。
8.新しい参照の追加で上のクラスライブラリプロジェクトを追加
9.フォームアプリ側でクラスライブラリプロジェクトの関数を実行する処理を実装
clsTest ctst;
ctst.Exec();

10.コンパイル→デバッグ実行→DLLを参照しようとしたタイミングでエラー発生!
「DLL参照時に指定されたモジュールが見つかりません。(HRESULT からの例外 0x8007007E) が発生してしまう。」
*クラスライブラリ側の、DLLの関数を呼んでいる部分をコメントアウトするとエラー無く実行できてしまいます。

C++プロジェクト(Windowsフォームアプリ)を作成し、あるサイトで公開されているDLLを実装し→コンパイル→デバッグ実行させた所、問題なく動作が確認できたのですが、
クラスライブラリで作成したC++新規プロジェクトに同じくDLLを実装し、同一ソリューション内にC#又はC++でWindowsフォームアプリを作成し、先に作成したクラスライブラリプロジェクトを参照させる形態で作成した際に、コンパイル→デバッグ実行させた所、コンパイルは通ったのですがデバッグ実行時に、DLLを参照しようとしたタイミングで
「DLL参...続きを読む

Aベストアンサー

やるならば ソリューション名をつけて複数のプロジェクトをまとめたほうがいいように思います

VC++/C#で新規にプロジェクト(ソリューション)を生成する際のダイアログの『ソリューションのディレクトリを作成』にチェックを入れて
『USBIODEMO』などといった具合にします
その中に.NET用のクラスライブラリのプロジェクトを作成します
こうすると
USBIODEMO\Debug(または Release)に出来上がったDLLが生成されます
同じように テスト用のFormアプリをVCのプロジェクトで作成します
コンパイル/リンクがうまくいけば 上記のフォルダに EXEが生成されます
この状態でFormEXEのデバッグを行ってやれば 質問のようなエラーは回避できると思います

C#の場合は 元の『USBIODLLDemo.dll』をC#のプロジェクトの『bin\debug(またはRelease)』にコピーしないといけないでしょう

つまりは クラスライブラリのDLLは見つかったが 元の『USBIODLLDemo.dll』が見つからなかった
という現象ではないかと思います

アプリの参照はクラスライブラリーまでなのでクラスライブのDLLまではコピーしたりする面倒を見てくれます
クラスライブラリが参照しているDLLまで面倒見てくれないためなのかもしれません

DLLの検索順についてWebなどで検索してみましょう

やるならば ソリューション名をつけて複数のプロジェクトをまとめたほうがいいように思います

VC++/C#で新規にプロジェクト(ソリューション)を生成する際のダイアログの『ソリューションのディレクトリを作成』にチェックを入れて
『USBIODEMO』などといった具合にします
その中に.NET用のクラスライブラリのプロジェクトを作成します
こうすると
USBIODEMO\Debug(または Release)に出来上がったDLLが生成されます
同じように テスト用のFormアプリをVCのプロジェクトで作成します
コンパイル/リンクがう...続きを読む

Qアプリケーション終了時例外エラー(アクセス違反)の調査方法について

大変困っています。

アプリケーションが終了するときに「アクセス違反」がワトソン博士によって取得されています。
当方アプリケーションなどに弱く、解決策の想像が付きません。どなたかご教授お願いいたします。

<解決策例>
・どういったスキルを持った人にどの様な調査を進めさせれば良いのか。。。
・以前同様な事があり原因は○○だった
・恐らく○○だろう
 など、お願いいたします。

<ユーザ報告>
処理終了し、画面が消えたところでワトソン博士のメッセージが表示された

<ログ抜粋>
例外番号c0000005(アクセス違反)

ファンクション:RtlDestroyHeap
~略~
フォールト → 77f6d672 8908 mov [eax],ecx ds:09000001=00000000

<備考>
開発環境:MSVC6.0
動作環境:Windows NT4.0 SP6a
発生頻度:2回/年
使用頻度:2~3回/(平日)

以上、よろしくお願いします。

Aベストアンサー

発生頻度が年2回というのはなかなか厳しい条件ですね。

さて・・・

「私であれば、次の手順で調査を行います。」という書き始めで延々とデバッグ方法を書いていたのですが、書き終わってからちょっとGoogleで検索したら、ひょっとするとちょうど質問者さんのトラブルと同じかもしれない現象がMicrosoftのKBにありました。

場所はここです: http://support.microsoft.com/kb/168006/ja

要点をかいつまんで書くと、MSVCRT/MFCのDLLのバージョン不整合でエラーが発生することがある、という内容です。KB自体は特定のアプリケーションについて書かれていますが、記述されている現象と原因の関係から考えるに、他のアプリケーションでも同様の現象が発生すると思われます。

さてさて。

せっかく書いた文章を捨てるのがもったいないので(貧乏性)、邪魔かもしれませんが下に続けることにします。もし上のKBの内容がそれらしいようであれば、読み飛ばしてください。

========

私であれば、次の手順で調査を行います。

1. MAPファイル、CODファイル作成

「ワトソン博士のログを取得した際に実行していたEXEファイル」をビルドした際、一緒にMAPファイルやCODファイル(リスティングファイル)を作成していれば、そのファイルを用意しておきます。

もし作成していない場合は、「ワトソン博士のログを取得したEXEファイル」と、バイナリレベルで全く同じEXEファイル(バイト単位で比較すると、ファイルに埋め込まれたタイムスタンプ・チェックサム以外は一致する)が作成可能かどうか調べます。(ビルドに必要なソースファイルやビルドオプションに変更を加えていなければ作成可能です。)

作成可能であれば、コンパイルオプションに「リスティングファイルタイプ:マシン語コードとソースを含む」、リンクオプションに「MAPファイル作成」を追加してEXEを再作成してください。これで、「ワトソン博士のログを取得した際に実行していたEXEファイル」に対応するMAPファイルとCODファイルが得られます。

2. エラー発生行を特定

ワトソン博士のログがどれだけ取れているかにもよりますが、スタックダンプが含まれていればたいていエラー発生行を特定できます。

まず「フォールト->」が含まれる逆アセンブルリストを探します。次に、その下にある「スタックバックトレース」を探します。

スタックバックトレースを上から下に順にたどっていくと、そのうち「ReturnAd」(リターンアドレス)がアプリケーションのアドレス範囲(VC++6の標準オプション設定を変更していなければ0x00400000~)に入るところが出てきます。見つかったら、そのアドレスの直前にあるcall命令が例外を発生させたAPIを直接呼び出している場所です。

さて、仮にリターンアドレスが0x00401234だったとします。そうしたら、次はMAPファイルを見てこのアドレスがどの関数に属しているか探します。ちょうど0x00401234というアドレスは見つからないでしょうけれども、これに近いアドレスは見つかるはずです。そのアドレスに対応する関数名もMAPファイルにあります。

次はその関数名をCODファイルから探します。見つかったら、MAPファイルにあるアドレスがCODファイルにあるマシン語コードの先頭アドレスになるので、そこからリターンアドレス0x00401234に対応するはずの場所まで順番にアドレスを辿っていきます。関数の先頭アドレスが0x00401200であれば、0x34バイト先を探すわけです。

そうすると、その探した場所にある命令の直前の命令がcall命令になっているはずです。CODファイルには、その場所のC++ソースでの行番号とソース文もコメントとして入っているはずなので、あとは対応するソースをよーく見てエラーの見当をつけてください。

アセンブラの知識があれば、そこでcallを使った(他の関数を呼び出した)ときの引数の内容もある程度分かります。(ポインタ渡しだと、そのポインタの先の内容までは分かりませんが。)

3. 置き換え用EXEファイルと対応するMAPファイル作成

これ以降は将来への備えです。

コンパイルオプションでデバッグ情報を「プログラムデータベースを使用」、リスティングファイルタイプを「マシン語コードとソースを含む」、リンクオプションで「MAPファイルを作成する」、デバッグ情報「他の種類」を追加してビルドし、出来たEXEファイルを本番用として使用します。同時に作成されるMAPファイル、CODファイル、PDBファイルは保管しておきます。

MAPファイル、CODファイルの使い方は上記2.のとおりです。PDBファイルは、もし完全なクラッシュダンプが取得できればWinDbgを使って事後ソースレベルデバッグが可能になりデバッグ作業が非常に楽になるので、念のため取っておきます。

4. ワトソン博士のオプション変更

drwtsn32.exeを起動し、「クラッシュダンプファイルの作成」をチェックします。(デフォルトは、チェックが入っています。)

クラッシュダンプファイルとEXEとPDBがあればWinDbgで事後ソースレベルデバッグができます。(いわゆるポストモーテムデバッグです。UNIX系でコアダンプしたコアをデバッガで読み込んでデバッグするのと同じ種類のものです。)


普段何とも思わずに行っていることでも、文章にすると長いですね・・・

えーと、「どういうスキルを持った人に調査させればいいか」については、上記の内容を読んで『なるほど!』と言える人でしょうか。

参考URL:http://support.microsoft.com/kb/168006/ja

発生頻度が年2回というのはなかなか厳しい条件ですね。

さて・・・

「私であれば、次の手順で調査を行います。」という書き始めで延々とデバッグ方法を書いていたのですが、書き終わってからちょっとGoogleで検索したら、ひょっとするとちょうど質問者さんのトラブルと同じかもしれない現象がMicrosoftのKBにありました。

場所はここです: http://support.microsoft.com/kb/168006/ja

要点をかいつまんで書くと、MSVCRT/MFCのDLLのバージョン不整合でエラーが発生することがある、という内容です。KB...続きを読む

QCStringからchar*への型変換について教えてください。

以前の質問に

int型 → CString型/char型

がありましたが、

CString型をchar*型に変換する方法を
教えていただければありがたいです。

MSDNで「LPCTSTRキャスト」が説明されていましたが、
例が載ってないのでよくわかりませんでした。

よろしくお願いします。

Aベストアンサー

目的にもよりますが一時的にchar配列として使いたいならCString::GetBuffer()が利用できます。
char配列としての利用が終わったらCString::ReleaseBuffer()する必要がありますが。

直接CString内の文字列を扱う必要があるならCString::operator LPCTSTRで文字列ポインタが得られます。
ただし、CStringオブジェクトをいじると無効ポインタなる可能性があるので気をつけてください。

MSDNのMicrosoft Foundation Classリファレンス→CString→クラスメンバで確認してください。

QcharからLPTSTRへの変換方法

リストコントロールにchar型の変数の値を数値として表示させたいのですが、charからLPTSTRへの洗練された変換方法がよくわからないです。

char tempChar;
CString tempString;
tempString.Format("%s", tempChar);
LPTSTR lpsz = new TCHAR[tempString.GetLength()+1];
_tcscpy(lpsz, tempString);

こんなプログラムを考えてみたのですが、汚いような気がします。もっと簡単で洗練された変換方法はないのでしょうか?

Aベストアンサー

wsprintfを使ってはどうでしょうか?

char tmpChar = 100;//表示する数値
TCHAR buf[5];
wsprintf(buf, "%d", tempChar);

Qデバッグ中のエラーのことで教えてください。

下のようなエラーが出て困っています。
コンパイルされているのですが、いろいろなサイトを調べましたが、どのようなエラーであるのかが結局わからなかったので、ここで質問しました。

プログラミング環境は、
Microsoft Visual Studio .NET 2003
です。
OSはWindows XP SP3
です。



Debug Assertion Failed!

File:dbgdel.cpp
Line:52

Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

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



というエラーが出ます。

メモリ容量、CPUに関しては4GB,クロック3GHzのクアッドコアを使用しているので、ここで問題が発生しているとは考えられないです。一体、どのようなエラーなのでしょうか???



よろしくお願いします。

下のようなエラーが出て困っています。
コンパイルされているのですが、いろいろなサイトを調べましたが、どのようなエラーであるのかが結局わからなかったので、ここで質問しました。

プログラミング環境は、
Microsoft Visual Studio .NET 2003
です。
OSはWindows XP SP3
です。



Debug Assertion Failed!

File:dbgdel.cpp
Line:52

Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

For information on how your program can cause an assertion failure, see the Visul C++ ...続きを読む

Aベストアンサー

これはランタイムエラーなのですが
dbgdel.cpp:52が悪いわけではなく
それを読んでいるプログラムが悪いのです
コールスタックを表示してみてください(デバッグ->ウィンドウ->呼び出し履歴かな?)

例えば次のプログラム
char* p = new char;
delete p;
delete p;
これで確実に同じエラーとなります
エラーダイアログが表示されたら「再試行(R)」を選んでください
コールスタックには以下のような表示が出ます
質問者が言っているのはAですが、ここが悪いのではなく
これを呼んだBが悪いのです
(Bをダブルクリックすると、該当ソースに飛びます)
A.skelton.exe!operator delete(void * pUserData=0x00bb5b48) 行 52 + 0x51 バイトC++
B.skelton.exe!WinMain(HINSTANCE__ * hInst=0x00400000, HINSTANCE__ * __formal=0x00000000, HINSTANCE__ * __formal=0x00000000, HINSTANCE__ * __formal=0x00000000) 行 512 + 0x15 バイトC++
C.skelton.exe!__tmainCRTStartup() 行 324 + 0x35 バイトC
D.skelton.exe!WinMainCRTStartup() 行 196C

これはランタイムエラーなのですが
dbgdel.cpp:52が悪いわけではなく
それを読んでいるプログラムが悪いのです
コールスタックを表示してみてください(デバッグ->ウィンドウ->呼び出し履歴かな?)

例えば次のプログラム
char* p = new char;
delete p;
delete p;
これで確実に同じエラーとなります
エラーダイアログが表示されたら「再試行(R)」を選んでください
コールスタックには以下のような表示が出ます
質問者が言っているのはAですが、ここが悪いのではなく
これを呼んだBが悪いのです
(...続きを読む

QC#で、あるクラスのメンバーすべての値を出力したい

C#の勉強したて(Cの知識もへっぽこ)なので、以下のことをしたいのに、
さっぱりやり方が分かりません。
教えて君みたいな質問ですが、心の大きい方、どうぞ教えてくださいませ。

★やりたいこと
他クラスのメンバー全部に値を入力し、かつそれを出力したい。
なお、他クラスのメンバーは数十個あるので、一つづつ代入&出力ではなく、
ループ文を使ったようなもので行えないかと模索中。


★例

//住所録ファイルの内容をコンソール出力するプログラム。
using System;

class Data_Format {
  public string name;
  public string address;
  public string age;
}

class App{

  public static void Read_Data(ref Data_Format obj){
    obj.name = 略) テキストファイルの1行目から読込め
    obj.address = 略) テキストファイルの2行目から読込め
    obj.age = 略) テキストファイルの3行目から読込め
  }

  public static void Main() {
    Data_Format ob = new Data_Format();

    App.Read_Data(ref ob);

    Console.WriteLine(ob.name);
    Console.WriteLine(ob.adress); 
    Console.WriteLine(ob.age);
  }
}


この例では

Mainメソッドで、
3個のオブジェクト(ob.name, ob.address, ob.age)の内容を出力させるのに、
Conosole.WriteLineの文を3個書いています。

さらに、Read_Dataメソッドで
3個のオブジェクト(ob.name, ob.address, ob.age)の値を入力するのに、
3行費やしています。
(↑ファイルの1行目から順番に読ませるので、効率化できる??)

しかし、実際に作りたいプログラムはメンバーが数十個あるので、
ループ文等を使えれば、効率よくなるのかな悪それでもいいのですが、
もっといい方があればご教授下さい。

C#の勉強したて(Cの知識もへっぽこ)なので、以下のことをしたいのに、
さっぱりやり方が分かりません。
教えて君みたいな質問ですが、心の大きい方、どうぞ教えてくださいませ。

★やりたいこと
他クラスのメンバー全部に値を入力し、かつそれを出力したい。
なお、他クラスのメンバーは数十個あるので、一つづつ代入&出力ではなく、
ループ文を使ったようなもので行えないかと模索中。


★例

//住所録ファイルの内容をコンソール出力するプログラム。
using System;

class Data_Format {
 ...続きを読む

Aベストアンサー

リフレクションを使えば動的に取得できます。

public class Data_Format
{
public string s1 = "1";
public string s2 = "2";
public string s3 = "3";

public string members()
{
string ret = "";
try
{
System.Reflection.FieldInfo[] fields = this.GetType().GetFields();
foreach(System.Reflection.FieldInfo f in fields)
{
ret += (string)f.GetValue(this) + "\n";
}
}
catch(Exception)
{
}
return ret;
}
}

QDWORDの実際の型は何でしょうか

VC++.NETの環境です。
DOWRD dw1 = 1;
int i = 2; と定義し
ここで
if ( i > dw1 ){
何かの処理;
}
とコーディングすると
warning C4018: '>' : signed と unsigned の数値を比較しようとしました。
のワーニングがでます。
これは、DWORDがint型でなくunsigned int型のようにも見えます。
ある本によれば(VC++.V.NET逆引き大全500の極意)
DWORD はint型であると記述されています。
もし、int型ならこのワーニングはでないはずなのですが、
なぜでるのでしょうか。又、DWORDの実際の型は何なのでしょうか。ご存じのかたおりましたら、教えていただけませんでしょうか。

Aベストアンサー

型定義が知りたいのならば、宣言ファイルを見れば疑問を挟む余地もありません。
DWORD型はwindef.hで
"typedef unsigned long DWORD;"
と宣言されています。

Visual Studioを使っているのならば、知りたい型の上にマウスポインタを置いて右クリック、ポップアップメニューの「定義へ移動」または「宣言へ移動」で簡単に知ることが出来ます。


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング