質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.33%

  • C#

    7707questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

64bitでコンパイルするとMarshalクラスのAllocHGlobalメソッドでエラーが発生

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 198

shiode

score 1

現在、C#でシステムを作っています。
自作の印刷プレビュー画面にて、印刷ボタン、余白設定、レポート設定ボタンを配置し、
其々のボタンを押下した際の情報を保持し、印刷時に反映させるようになっています。

開発、実行OS:Windows10 64bit
開発ツール:VisualStudio2017
フレームワーク:4.6.2
ビルドの際、プラットフォームは、64bitを使用

プリンタ情報を読み込む為のロジックにて、★印の部分でエラーが発生します。

/// <summary>
/// プリンター情報を読み込む
/// </summary>
/// <param name="doc">ドキュメント</param>
/// <returns>ポインタ</returns>
private IntPtr mintLoadPrinterSetting(Document doc)
{
IntPtr devPtr;

// 設定ファイル名
string wstrFileName = Path.Combine(Application.StartupPath,
mstrPrtSetNmReplace(doc.Printer.PrinterSettings.PrinterName) + ".prt");

// ファイルが存在する場合
if (File.Exists(wstrFileName))
{
using (FileStream fs = new FileStream(
wstrFileName, FileMode.Open, FileAccess.Read))
{
// 読み込み
byte[] setting = new byte[fs.Length];
fs.Read(setting, 0, (int)fs.Length);

// グローバル領域にメモリー確保
devPtr = Marshal.AllocHGlobal(setting.Length);

// 設定コピー
Marshal.Copy(setting, 0, devPtr, setting.Length);

// ファイルクローズ
fs.Close();
}
}
else
{
devPtr = Marshal.AllocHGlobal(doc.Printer.PrinterSettings.GetHdevmode()); ★
}

return devPtr;
}

エラーメッセージ:

プログラムの実行を続行するための十分なメモリがありませんでした。

試したこと:

ビルドの際、プラットフォームを、32bitを使用したところ、エラーは発生しませんでした。

デバック時に doc.Printer.PrinterSettings.GetHdevmode() の内容を確認したところ、

64bit実行時:0x000001d532fe02d8
32bit実行時:0x13893020

でした。

実行環境のメモリ使用量は、32bit実行時も、64bit実行時も変わらず、
めいっぱい使っているようには見受けられません。(実行環境は、メモリ8GB搭載)

32bitと64bitでポインタの扱いが違うといった情報は
いろいろと出てくるのですが、対処方法が分かりません。

エラーの原因、対処法について、教えて頂きたいです。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

0

64bit実行時:0x000001d532fe02d8

2Tを超える領域を確保しようとしてますが、それはムリということなんでしょうね

doc.Printer.PrinterSettings.GetHdevmode() という関数が何を返すのか、調べてみてはどうでしょうか

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/10/12 16:49

    doc.Printer.PrinterSettings.GetHdevmode() について調べてみました。

    プリンタ設定に対応する DEVMODE 構造体を識別するハンドルを返す関数でした。
    メモリ領域を確保する関数であるMarshal.AllocHGlobal()に引数として渡していることに問題があると判断しました。
    ソースを修正し、正しい値でメモリ領域を確保しようと思います。

    アドバイスを頂き、ありがとうございました。
    大変参考になりました。

    キャンセル

0

ざーっと調べた限りAllocHGlobalは誤りでpinvoke使ってGlobalLockしないといけないようです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/10/17 13:30

    回答頂き、ありがとうございます。

    私が、pinvokeやGlobalLockが何か、
    どのように使うのかが分からないので、
    2つの内容を調べて、確認してみます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.33%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • C#

    7707questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。