0

C++ で記述している dll に問題があります。私が自分で解決できなかったいくつかの非常に奇妙な動作が進行中です。

何が起こっているのかを正確に説明するのは難しいですが、最善を尽くします。基本的に、DLL には、1 つのプライベート プロパティとパブリック コンストラクターを持つクラスがあります。このクラスを初期化してからプログラムを終了すると、エラーが発生します。

「実行時チェックの失敗 #2 - 変数 'test' の周りのスタックが壊れていました」

私はここに2つのプロジェクトを持っています:

  1. 「 testdll 」という名前の DLL 。
  2. 「 test 」という名前のコンソール テスト プログラム。

考えられる原因を絞り込むために、このエラーを最も単純な再現可能な形式に要約しました。以下に私のコードを示します。

プロジェクト "testdll"、ファイル testdll.h:

#include <string>

class testdll
{
public:
__declspec(dllexport) testdll(); // Empty but same error if prams are used.

private:
std::string _var;
};

プロジェクト「testdll」、ファイル testdll.cpp:

#include "testdll.h"

testdll::testdll()
{
}

プロジェクト "test"、ファイル testdll.h:

#include <string>

class testdll
{
public:
    __declspec(dllimport) testdll();
};

プロジェクト "test"、ファイル stdafx.h:

#pragma once

#include "targetver.h"

#include <tchar.h>

プロジェクト "test"、ファイル test.cpp:

#include "stdafx.h"
#include "testdll.h"

int _tmain(int argc, _TCHAR* argv[])
{
testdll test;

return 0;
}

ご希望であれば、 Visual C++ 2010ソリューション ファイルを、ご希望のアーカイブ形式でお送りします。助けてください!何が起こっているのかわかりません。

オプション情報: 言語 (またはソフトウェア): C++

既に試しました: コンストラクター定義を削除します。これは機能しますが、使用可能なソリューションではなく、問題を説明するものでもありません。また、すべてのプライベート プロパティをポインターにすることもできますが、これを行う必要はありません。

4

2 に答える 2

1

2 つのヘッダー ファイルを使用していますが、同じクラスを宣言していません。一方には std::string メンバーがあり、もう一方にはありません。これは非常に悪いことです。コンパイラはスタック フレームにオブジェクト用の十分なスペースを確保していません。これは、実行時エラーが伝えていることです。非常に優れた機能ですが、この種の間違いを他の方法で診断するのは非常に困難です。

クラス全体ではなくコンストラクターに __declspec(dllexport) のみを適用したため、おそらくこのピクルに陥りました。dll プロジェクトとexe プロジェクトの両方で使用できるように、ヘッダー ファイルを作成する必要があります。次のようになります。

#undef DLLEXPORT
#ifdef BUILDING_MYDLL
#  define DLLEXPORT __declspec(dllexport)
#else
#  define DLLEXPORT __declspec(dllimport)
#endif

class DLLEXPORT testdll
{
public:
    testdll();
private:
    std::string _var;
};

DLL プロジェクト、プロパティ、C/C++、プリプロセッサ、プリプロセッサ定義を右クリックします。BUILDING_MYDLL を追加

そして、exe プロジェクト ディレクトリにある testdll.h ファイルを削除します。C/C++、一般、追加のインクルード ディレクトリ設定を設定して、コンパイラが testdll プロジェクト ディレクトリ (..\testdll など) でヘッダーを検出できるようにします。

于 2012-04-29T10:07:32.377 に答える
0

DLL からのクラスとクラス メンバーのエクスポートは、非常に壊れやすいことを発見しました。ライブラリとクライアントの両方が、あらゆる種類のコンパイラ設定に依存するまったく同じクラス レイアウトを使用していない場合、事態は恐ろしく失敗します。

あなたの場合、互換性のないバージョンのstd::stringinsideを使用している可能性がありclass testdllます。1 つはデバッグ用に、もう 1 つはリリース用にコンパイルされている可能性があります。または、1 つは静的ランタイム ライブラリを使用し、もう 1 つは DLL ランタイムを使用しています。誰が言えるの?

とにかく、C++ 機能を DLL からエクスポートするとすぐに、そのコンパイラのバージョンと設定にロックインされます。メンテナンスの悪夢です。

v テーブルのみの基底クラスまたは C 互換のラッパー関数を使用します。

于 2012-04-29T06:19:22.907 に答える