0

これは、私が今書いた関数の簡略化されたバージョンです。

int foobar(char * foo) {
  puts(type);
  struct node * ptr = (struct node *) malloc (sizeof(struct node));
  puts(type);
  memset(ptr, 0, sizeof(ptr));
  ptr=head;
  return head->id;
}

これは、 linklistnode内のノードとして宣言された単なる構造体でありchar *、次のノードへの およびポインターを含んでいます。ただし、malloc()ここで入力が破損していることに気付きましたchar * foo

malloc()入力 char ポインターが破損するのはなぜですか? また、ここで問題を解決するにはどうすればよいですか? 今、私はそのポインターの内容をローカル配列にコピーしているだけですが、これは私の好みでもハッキーすぎます (これは最善ではありません)。

ご意見ありがとうございます。

編集:まあ、ここにもっと実際のコードがあります:

void foobar(char * type) {
  puts(type); <-- here it's a long string about 30 char
  struct node * ptr = (struct node *) malloc (sizeof(struct node));
  puts(type); <- chopped of, 10 left with some random thing at the end
}

問題が今明らかになることを願っています!ありがとう!

編集:

type初期化の方法は次のとおりです。

type = strdup("Some ");
tempType = strdup("things");
sprintf(type + strlen(type), "%s", tempType);

ありがとう!

4

2 に答える 2

7

明らかな破損が発生するのは、typeまたはfooすでに解放されているメモリを指しているmalloc()ために、別の用途に使用できるようになるためです。

メモリを解放すると、それを使用し続けることはできません。

ptrに割り当ててから次のように消去するため、問題もありますptr

ptr = head;

次のことを意味している可能性があります。

head = ptr;

ptr->next = head;しかし、おそらくその前に設定する必要があります。もちろん、型定義を示していないため、これは憶測です。

またはhead->idの代わりに戻る理由も明らかではありません。残念ながら、「それは間違っている」と断言できるほどの情報はありません。それは普通ではありません。headptr


2nd Editの解説

タイプが初期化される方法は次のとおりです。

type = strdup("Some ");
tempType = strdup("things");
sprintf(type + strlen(type), "%s", tempType);

若干の不具合があります。あなたは、ビジネスで踏みにじっていない記憶を踏みにじっています。

最初の 2 行は問題ありません。文字列を複製します。ただし、これtypeは 6 バイトのメモリへtempTypeのポインタであり、7 バイトのメモリへのポインタであることに注意してください。

災害は3行目に発生します。

type + strlen(type)文字列の末尾にある null バイトを指していtypeます。tempType次に、多かれ少なかれ合法的に1バイトを書き込みます。null で終了する文字列はもうありませんが、最初のバイトは範囲内にあります。2 番目以降のバイトは、ユーザーに割り当てられていない領域に書き込まれ、メモリ割り当てに関する制御情報が含まれている可能性があります。

割り当てられたメモリの範囲外に書き込むと、「未定義の動作」が発生します。何でも起れる。一部のマシンでは、特に 64 ビット コンパイルでは、完全に回避できる場合があります。ほとんどのマシン、特に 32 ビット コンパイルでは、ヒープ メモリが破壊され、どこか (通常はこの場所から少し離れた場所) で問題が発生します。これがメモリ乱用の性質です。多くの場合、問題が発生する場所は機能しているように見えますが、他の場所で発生した問題に悩まされているのは、他の無害なコードです。

したがって、これらの文字列を連結したい場合は、次のようにする必要があります。

char *type = strdup("Some ");
char *tempType = strdup("things");
char *concat = malloc(strlen(type) + strlen(tempType) + 1);
sprintf(concat, "%s%s", type, tempType);

エラーチェックを省略しました。strdup()とからの割り当てをチェックして、malloc()メモリが割り当てられていることを確認する必要があります。snprintf();を使用すべきだと主張する人もいるかもしれません。前の行で必要なスペースを計算し、十分なスペースを割り当てたので、そうしないのは意識的な決定でした。しかし、少なくともそれを考慮する必要があります。使用可能な十分なスペースがあることを確認していない場合は、snprintf()バッファ オーバーフローを回避するために を使用する必要があります。また、その戻り値をチェックして、情報がすべてフォーマットされているかどうかを確認します。(また、解放するための 3 つのポインターがあることに注意してください。または、割り当てられたメモリが適切なタイミングで解放されるように、他のコードに渡します。)

Windows では、snprintf()(または_snprintf()) は C99 標準で指定された方法で動作しないことに注意してください。率直に言って、それは役に立ちません。

于 2012-04-12T01:26:31.987 に答える
5

何をしようとしているのかはわかりませんが、コメントは何が起こっているかを示しています。

// This allocates enough memory for a struct node and assigns it to ptr.
struct node * ptr = (struct node *) malloc (sizeof(struct node));

// This displays the data in the (unspecified) string type,
// which must be null terminated.
puts(type);

// This sets the first 4 bytes of ptr to 0, assuming pointers are 4 bytes.
// You probably want memset(ptr, 0, sizeof(struct node));
memset(ptr, 0, sizeof(ptr));

// This makes ptr point to the address of head, orphaning the memory
// that was just malloc'ed to ptr.
ptr=head;
于 2012-04-12T01:31:12.950 に答える