たびたびこの掲示板を利用させてもらっているものです。
以下質問があります。
typedef strcut{
CHAR* test;
CHAR tes[128];
}TEST;
というような構造体があった場合、以下のようにするとエラーが起きます。
void main()
{
TEST tTest;
CString s = aaa;
tTest = ( TEST* )calloc( 1 , sizeof( BYTE ) ) ;
strcpy( tTest->test , s ); // CHAR*型はアクセスバイオレーションになる。
strcpy( tTest->tes , s ); // こちらでは成功する。
}
いろいろ調べているのですが、なかなかわかりません。
どのような原因があるのか教えていただいたら幸いです。
【環境】
WinXP(SP1)
VC++6.0
以上、よろしくお願いいたします。
どっちもダメです。
動いているように見えるのはたまたまですから……。
1バイトしか確保していないですし……。
> tTest = ( TEST* )calloc( 1 , sizeof( BYTE ) ) ;
tTest = (TEST *)calloc(1, sizeof(TEST));
または,
tTest = new TEST;
さらに,
> strcpy( tTest->test , s ); // CHAR*型はアクセスバイオレーションになる。
tTest->testはオブジェクトを指していないです。
tTest->testはchar型の配列を指している必要があります。
ポインタについて,もう一度勉強してみると良いでしょう。
strcutだとか
TEST tTest;とかはいいの?
で、tTest->testもちゃんとnewしてあげればいいかな?
typedef struct TEST_t {
CHAR* test;
CHAR tes[128];
} TEST;
int main() {
TEST* tTest;
CString s = aaa;
tTest = (TEST*)malloc(sizeof(TEST)) ;
tTest->test = (CHAR*)malloc(s.GetLength()+1);
strcpy( tTest->test , s );
strcpy( tTest->tes , s );
free(tTest->test);
free(tTest);
return 0;
}
とりあえずうまくいきました。
ですが、何故そうなるのかいまいち理解できていないです。
なぜ、ダメだったかなどデバックしながら、
ポインタについて勉強しなおしてきます。(^^;
レスをしていただいた方々にお礼を申し上げます。
ほんとうにありがとうございました。
こんにちは
> ですが、何故そうなるのかいまいち理解できていないです。
>
> なぜ、ダメだったかなどデバックしながら、
基本的な概念がある程度身に付いていない状態でいきなりデバッガで追いかけても、
「なぜ正しく動作しないのか」という原因が正しく理解出来ないことも多いです。
(もちろんデバッガで追いかけるのは良いやり方ではありますが・・・)
そこで、とりあず一番ポイントとなるところだけ示させていただきますと・・・
> TEST tTest;
^^^^^
単純なコンパイルエラーとなるはずですが、TEST型のメモリを動的に確保するなら、
ポインタで受けなければなりません。
TEST *tTest;
^^^^^^
> tTest = ( TEST* )calloc( 1 , sizeof( BYTE ) ) ;
^^^^^^^^^^^^^^
YuOさんが指摘された「1バイトしか確保していないですし……。」の意味は、
上記のsizeof()で確保するメモリのサイズを取得する際に、
引数として渡しているのが「BYTE型」だからです。
確保したいメモリのサイズは、「本当はTEST型のサイズ」のはずですが、
上記のように指定すると「BYTE型」のデータサイズで「1つ分」しかメモリが
確保されていません。
> strcpy( tTest->test , s ); // CHAR*型はアクセスバイオレーションになる。
> strcpy( tTest->tes , s ); // こちらでは成功する。
YuOさんが「動いているように見えるのはたまたまですから……。」と
おっしゃられてるのは、確保されたメモリ領域が1バイトだけなので、
TEST型のオブジェクト(tTest)を格納する領域としては、
既に不十分であるためというのが一つにはあります。
また仮にtTestに正しい容量が確保されていたとしても、上のパターンではメンバの
「test」が何も指していない状態(どこを指しているのか不定な状態)なので、
書いてはいけない領域に無理矢理データをコピーしようとしていることになります。
これを理解した上で他の方のアドバイスや、正しいプログラムを参考にされると
容易に理解できるかと思います。