0

従うコードスニペット。

char * の数を格納する構造体 (コード例にはクラスがあり、両方を試し、同じ効果があります) があります。それらのほとんどを = ""; に初期化するクラスのコンストラクターを作成しました。クラスのインスタンスのそのメンバーを変更しようとすると、strncpy などのすべてのレポート アクセスが拒否されました。これらの関数は、内部の構造体/クラス メンバー関数のスコープで使用すると、アクセスが拒否されたと報告することさえあります。

構造体/クラスの char * メンバーを持つことは大したことではなく、特別なことではないと私の仮定でした (使用する前のある時点で初期化する必要があり、特定の時点で破棄する必要がある char へのポインターであることを除けば) )。

誰かが私の仮定が間違っている場所を教えてくれ、何が起こっているのかを明確にする文献を教えてくれたら幸いです. 現在、vs2008 フル エディションでコードをコンパイルしています。

このコードを実行すると、特定のメモリ ロケーションへのアクセスが拒否されたというランタイム エラーが発生することが予想されます。

また、char * mystr を作成すると、後で mystr = ""; と言ったときに、mystr が使用されるようにメモリが初期化されます。

また、私はばかではないと思いたいのですが、ローカルウィンドウを使用して特定の変数の正確なメモリ内アドレスを決定しようとすると、メモリがどこにあるかを教えてくれるアイデアが得られないようですです。私はメモリ ウィンドウで幸運を得る必要があります。しかたがない。

ヘルプ!前もって感謝します。私はこれらの愚かな char * を扱うのが嫌いです。なぜなら、私はいつも何らかの形でそれらを台無しにしてしまうからです。これを変更して、彼らが私をイライラさせるのではなく、ツールのように命令できるようにしたいと考えています。

ご検討いただきありがとうございます。ジョシュ

#include <stdio.h>
#include <string.h>



   class mystruct {
    public:
 int A;
 char* B;
 char* C;

 mystruct() {
  A = 0xFE;
  B = new char[32];
  B = "";
  C = "test";
 }

 void test(char *input) {
  strncpy(B,input, strlen(input));
 }
    };

    int main(char* argv[], int argc) {

 mystruct work;
 char wtf[32];

    // work.A = 0xbb;
 work.test("gotchabitch!");
    // sprintf(wtf, "address of work is %x" , &work);
    // strncpy(work.C,"gotchabitch!\0",strlen("gotchabitch!\0"));
  strncpy(work.B,"gotchabitch!",strlen("gotchabitch!"));
 printf("%d;%s;%s;", work.A, work.B, work.C); 

 return 0;
    } 

すべてへの応答: わかりました。文字列リテラルを char * に代入すると、実際には char * const B = "something" と言っていることがわかりました。(前者が変更できないメモリへのポインタであるのに対し、後者はアドレスを変更できないポインタである const char * B = something とは異なりますか?)。いずれにせよ、これは私が得たエラーメッセージを説明しています。ありがとうございました。

4

3 に答える 3

1

エラーは次の行にあります。

C = "test";

mystruct のコンストラクターで。 "test"は読み取り専用メモリへのポインターであるため、これを使用して非 const ポインターを初期化するのは安全ではありません。コンパイラがこれを強制しない唯一の理由は、人々が const-correctness を気にする前に作成された膨大な量の C コードです。これは宣言されるべきですが、宣言されconstていません。

B = "";

同様にタイプセーフではありません。

于 2010-07-11T01:18:47.893 に答える
1
B = new char[32];
B = "";

最初に によって返されたポインタをnewtoBに割り当て、次に文字列リテラル""へのポインタを to に割り当てて、 によって返されBたポインタを効果的に上書きしますnew

Jonathan Leffler が説明しているよう""に、文字列リテラルは読み取り専用であるため、 が指す文字列リテラル ( )に書き込もうとするとエラーが発生しますB

空の文字列を に格納する場合はB、 のようなライブラリ関数strcpy()(または、できれば のようなより安全な関数snprintf()) を使用する必要があります。この場合、同じことなので、に割り当てることもでき\0ますB[0]。C および C++ では、 を使用して配列 (または単なる文字の配列である C 文字列) を割り当てることはできません=

理想的にはstd::string、生の C 文字列の代わりに使用する必要があります。そうすれば、この種のことを心配する必要はありません。

于 2010-07-11T00:42:31.990 に答える
1

問題は、あなたがやろうとしたときです:

strncpy(work.C, "something", strlen(something));

読み取り専用データをコピーしています - これは良い考えではありません。これは、ポインタ C が文字列リテラルを指しているためです。文字列リテラルの上書きは許可されていません。同様のコメントが B にも当てはまりますが、メモリ リークも発生しています。

重要な点は、「コンパイル時」エラーではなく「実行時」エラーについてのコメントです。メンバーにアクセスできないわけではありません。あなたが持っているように初期化したとき、それは悪用できません。

于 2010-07-11T00:44:45.713 に答える