0

私はCで次のようなことをしています:

void *initialize()
{
    my_type *ret = malloc(sizeof(my_type));
    return (void*)ret;
}

void test()
{
    my_type* ret = (mytype*)initialize();
    my_type x = *ret;
}

次の逆参照でクラッシュします。

Received signal 11 (Segmentation fault: 11)

ポインターが null ではありません: ポインターを出力してみましたが、値が得られました。

また、次のように、テスト関数で新しい my_type を作成しようとしました。

my_type* new = malloc(sizeof(my_type));

new と ret の整数表現を出力すると、それらは互いに非常に近い整数です。したがって、これらのことはメモリ内で近くにある必要があります。

4

4 に答える 4

2

コンパイラが関数を認識しない場合、intその戻り値の型として想定されます。

のサイズがint関数が実際に返すものと異なる場合、コンパイラによって生成されたコードは正しいバイト数を返さない可能性があります。

ただし、投稿したコードは正しく、使用される前に発生するように期待どおりに動作するinitialise()ため、コンパイラは関数が返す型を既に認識しています。

ほとんどの場合、元のコード (投稿していません) は次のようになります (のプロトタイプなしinitialise()):

次のことを試してください。

#include <stdlib.h> /* To pull in malloc's protoype. */

void * initialize(void);

void test()
{
    my_type x, * ret = initialize();
    if (ret)
      x = *ret;
}

void * initialize(void)
{
    my_type * ret = malloc(sizeof(*ret));
    return ret;
}
于 2013-05-14T17:41:18.100 に答える
1

名前が近い2つのタイプがあるようです

mytypemy_type

my_type *ret = malloc(sizeof(mytype));

my_type* ret = (mytype*)initialize();

同じタイプに 2 つの異なる名前を使用するのはタイプミスである可能性があります。これによりクラッシュが発生する可能性があります

于 2013-05-14T17:33:48.713 に答える
1

オッズはfield、(a) char 配列、(b) char へのポインター、または (c) 整数値のいずれかです。はい?

3 つのケースすべてにおいて、printf() ステートメントはfield、NULL 終了文字ストリングへのポインターであると想定しています。少なくとも提供するコード例では、何にも初期化されていません。

だから... SIGSEGVはfield、(a)が初期化されていないchar配列であり、printf()がヌルターミネータを探して読み取っているメモリの範囲を誰が知っているか、(b)フィールドが初期化されていないポインタであるためです...ゼロではない、有効なメモリアドレスであることを意味しない、または (c) 整数またはその他の値を char へのポインタとして printf() に渡そうとしていますが、そうではありません。

これら 3 つのいずれかが、報告する結果を生成します。

于 2013-05-14T17:24:14.187 に答える
0

あなたのコメントによるとfieldintそうです

printf(mytype->field);

する必要があります

printf("%d\n", ret->field);

cplusplus サイトのprintf()ページから

int printf ( const char * format, ... );

フォーマットされたデータを stdout に出力する

format が指す C 文字列を標準出力 (stdout) に書き込みます。format に書式指定子 (% で始まるサブシーケンス) が含まれている場合、format に続く追加の引数が書式設定され、結果の文字列に挿入され、それぞれの指定子が置き換えられます。

于 2013-05-14T17:24:33.417 に答える