1
#include <stdio.h>
#include <stdlib.h>

int main() {
    void *malloc(size_t size);
    char *ptr, *retval;
    ptr = (char *)calloc(10, sizeof(char));

    if (ptr == NULL)
        printf("calloc failed\n");
    else
        printf("calloc successful\n");

    retval = realloc(ptr, 5);

    if (retval == NULL)
        printf("realloc failed\n");
    else
        printf("realloc successful\n");

    free(ptr);
    free(retval);
}

これが私のコードです。14行目でエラーが発生します。

「void*」から「char*」への無効な変換

4

4 に答える 4

10

mallocの場合と同じように、reallocの結果を(char *)にキャストすることができます。

retval = (char*)realloc(ptr, 5);

皮肉なことに、あなたが書いたものは完全に合法的な「C」コードですが、キャストが必要なC++ではありません。したがって、C ++を実行していないので、コードを「C」としてコンパイルするようにコンパイラーを設定してみることもできます。これにより、問題は同様に解決されます。とはいえ、上記の変更も完全に合法的なCです...したがって、C++およびCでコンパイルされます。

編集:softyが正しく指摘しているように、ptrを再割り当てし、ポインタの場所をretvalに格納します。これは、ptrが無効なメモリを指している可能性があるため、解放しないでください。せいぜい同じメモリを2回解放し、最悪の場合、(reallocによって)すでに解放されているメモリに対してfreeを呼び出します。いずれにせよそれは悪い(tm)。それはあなたがいくつかの深刻な「未定義の振る舞い」を引き起こしているからです。

于 2012-05-21T18:12:23.340 に答える
1

ポインタを2回解放することはできません。ここで、retvalとptrは両方とも同じ場所を指しており、このコードを追加して、解放呼び出しの前に確認してください。

printf("%p \n ",ptr);
printf("%p \n",retval);

reallocのサイズは縮小されていますが、ポインターの位置は同じままです。あなたもこれを試すことができます:

if(ptr == retval)

/* delete either ptr or retval - just for sake of this programm , Idealy you shouldnt free the the pointer like this as Rightly Suggested by **Goz** in C++/c*/

それを機能させるためだけに、それ以外の場合はgccで正常にコンパイルされますが、実行すると、同じポインタを2回解放しようとしているため、ダーティスタックトレースが生成されます。それへのポインタ。サイズを30または50拡大すると、異なるポインタが得られる場合があります。

rgds、Softy

于 2012-05-21T18:22:37.077 に答える
1

他の人はあなたのCコードがC++コードとしてコンパイルされていることに気づきました。Cではキャストは不要ですが、C++では必須です。C ++では、ベクトル(または文字列)を使用する必要があります。

コードに関するいくつかの所見は次のとおりです。

  1. mallocを再宣言しないでください。stdlib.hを含めると、それが可能になります。ありがたいことに、あなたはその宣言を首尾よく複製したので、それは冗長であるだけです(そしてコードを読んでいる他の誰かを混乱させます)。宣言を間違えた場合、未定義の動作があります。

  2. reallocが成功した場合は、「ptr」を解放しないでください。

  3. 一部の難解なシステムでは、callocが期待どおりに機能しない場合があると指摘する人もいるかもしれません(特にポインター型と浮動小数点型の場合)。とにかく動的に割り当てられたスペースを適切な値で初期化する必要があることを考えると、mallocよりもcallocを呼び出す必要はありません。

于 2012-05-21T18:41:12.593 に答える
0

コンパイルしたい場合は、Cコンパイルを使用してください。C++コンパイルを使用しているように見えます。有効なCですが、有効なC++ではありません。ほとんどのコンパイラでは、小文字の.c拡張子を使用すると、コンパイラは自動的にCコンパイルを使用します。.cppはC++コンパイルを引き起こし、.C(大文字)はC ++コンパイル(たとえばgcc)を引き起こす可能性があります。

于 2012-05-21T18:31:06.917 に答える