- PR -

オブジェクト参照がオブジェクト インスタンスに設定されていません

1
投稿者投稿内容
未記入
会議室デビュー日: 2007/12/28
投稿数: 4
投稿日時: 2007-12-28 19:03
C#でunsafeにして部分的に過去の遺産のCでも実行できるようにポインタを使った行列を扱いたいのですがこのエラーが出てしまいます。ビルドはエラーを出しませんが実行時エラーとなります。わかる方ご教示いただきたく。

unsafe static void test_()
{
int i,j,n=5;
double** A = stackalloc double *[10];
double* d = stackalloc double[10];

for(i=0;i<n;i++)for(j=0;j<n;j++) A[i][j]=0.0;//ここでエラー代入がだめ
}
Hongliang
ぬし
会議室デビュー日: 2004/12/25
投稿数: 576
投稿日時: 2007-12-28 19:09
引用:
C#でunsafeにして部分的に過去の遺産のCでも実行できるように


仰る意味がよく分かりません。

引用:
コード:
double** A = stackalloc double *[10];
double* d = stackalloc double[10];

for(i=0;i<n;i++)for(j=0;j<n;j++) A[i][j]=0.0;//ここでエラー代入がだめ
}



d を使ってないのはともかくとして。
A はポインタの配列を用意しただけでそのそれぞれのポインタはなにも指してませんね。
A[i] がなにも指してないからそれの [j] を使えません。
未記入
会議室デビュー日: 2007/12/28
投稿数: 4
投稿日時: 2007-12-28 22:40
配列を宣言して、ポインタの配列のポインタに代入しても、

・ローカルの変数 'A' をこのスコープで宣言することはできません。これは、'親またはカレント' スコープで別の意味を持つ 'P' の意味が変更されるのを避けるためです。

・型 'double[]' を型 'double**' に暗黙的に変換できません。

とエラーが出て初期化ができません。メモリの確保についてアドバイスいただけませんでしょうか?

double** A = stackalloc double*[10];
double[] a = new double[] {5,4,3,2,1},

fixed(double *A=a){for(i=0;i<n;i++) A[0][i]=a[i];}
大ベテラン
会議室デビュー日: 2006/06/28
投稿数: 116
投稿日時: 2007-12-29 02:15
興味がわきましたので試してみました。
最初は、四角形型の多次元配列を作成しようと試みましたが失敗しました。
(無理なのでしょうか?)

そこで、Hongliangさんの以下の書き込み
引用:

Hongliangさんの書き込み (2007-12-28 19:09) より:
d を使ってないのはともかくとして。
A はポインタの配列を用意しただけでそのそれぞれのポインタはなにも指してませんね。
A[i] がなにも指してないからそれの [j] を使えません。


と、未記入さんの最初の書き込み
引用:

未記入さんの書き込み (2007-12-28 19:03) より:
double** A = stackalloc double *[10];
double* d = stackalloc double[10];


を組み合わせて
A[0] = d;
という風に定義するとジャグ配列として定義できました。
(とおもいます。動いているのでこれで良いと思いますが、MSDNでunsafe多次元配列の
記述が探せなかったのでちょっと確証が持てません。)

後、既存のコードを「過去の資産」と呼ぶのであればともかく、
C言語を「過去の遺産」と呼ぶのはどうかとおもいますよ。
未記入
会議室デビュー日: 2007/12/28
投稿数: 4
投稿日時: 2007-12-29 09:13
コメントありがとうございます。
ただ、私がA[0]=d;をやったところ、構文エラーですとエラーになってしまいました。

Cを過去の遺産といったのは失言しました。既存の財産というところです。
(固有値問題のQR法のソースです。)
Hongliang
ぬし
会議室デビュー日: 2004/12/25
投稿数: 576
投稿日時: 2007-12-29 10:33
引用:

暁さんの書き込み (2007-12-29 02:15) より:
最初は、四角形型の多次元配列を作成しようと試みましたが失敗しました。
(無理なのでしょうか?)


もともと stackalloc は C 言語の alloca に対応するものであって、配列ではありません。宣言の形としては配列を宣言しているようにも見えますけど。
それに多次元配列は容易に大きくなるため、限られた資源であるスタックに置くべきものではないでしょう。配列を fixed すればヒープにおいたままポインタとして扱えます。
一応、fixed な配列フィールドを持った構造体を stackalloc するとか、まず大きく stackalloc してその特定要素ごとのポインタを配列や stackalloc によるポインタのポインタとして持つとかで代用はできます。


引用:

未記入さんの書き込み (2007-12-29 09:13) より:
ただ、私がA[0]=d;をやったところ、構文エラーですとエラーになってしまいました。


エラーになった理由もメッセージに出てるでしょうし、あとはその構文エラーをなくすだけですね。

[ メッセージ編集済み 編集者: Hongliang 編集日時 2007-12-29 10:34 ]
未記入
会議室デビュー日: 2007/12/28
投稿数: 4
投稿日時: 2007-12-29 11:59
すみません。半分わかったようなわからないような状態です。
恐れ入りますが、サンプルコードを書いていただけませんでしょうか?

double[][] AA = new double[10][];
double** A = stackalloc double*[10];

fixed (double** A = (double **)&AA[0])//エラー
大ベテラン
会議室デビュー日: 2006/06/28
投稿数: 116
投稿日時: 2007-12-29 13:13
引用:

Hongliangさんの書き込み (2007-12-29 10:33) より:
引用:

暁さんの書き込み (2007-12-29 02:15) より:
最初は、四角形型の多次元配列を作成しようと試みましたが失敗しました。
(無理なのでしょうか?)


もともと stackalloc は C 言語の alloca に対応するものであって、配列ではありません。宣言の形としては配列を宣言しているようにも見えますけど。


なるほど。
勉強になります。
引用:
それに多次元配列は容易に大きくなるため、限られた資源であるスタックに置くべきものではないでしょう。配列を fixed すればヒープにおいたままポインタとして扱えます。


うーむ。確かに再帰とかするとまずそうですね。
stackalloc同様、fixedを知らなかったので試してみました。
コード:
    double[,] A = new double[10, 10];
    fixed(double* pA = &A[0,0]) {
        pA[0 * 10 + 1] = 5.5;
    }
    Console.Write("double:{0}", A[0,1]);


今回はジャグ配列を扱えなくなりました
アクセス記述子の理解が低いので、他にもっと良い方法があるのかもしれません。
実際にCから利用する場合にはこの点が問題になることはまず無いと勝手に思ってますが。
引用:
一応、fixed な配列フィールドを持った構造体を stackalloc するとか、まず大きく stackalloc してその特定要素ごとのポインタを配列や stackalloc によるポインタのポインタとして持つとかで代用はできます。


これらも掘り下げてやってみたいところです。

引用:

未記入さんの書き込み (2007-12-29 11:59) より:
すみません。半分わかったようなわからないような状態です。


私がそうでしたが、fixedキーワードについて調べて、
変数がマネージドかどうかを意識するようにすると理解が一気に進むと思います。
なお、先の"A[0]=d;"の私の書き込みではfixedは関係しません。
1

スキルアップ/キャリアアップ(JOB@IT)