1

次の関数があるとします。

float *dosomething(const float *src, const int N)
{
    float *dst = (float *)malloc(sizeof(float) * N);
    if(!dst)
    {
        printf("Cannot allocate memory\n");
        exit(EXIT_FAILURE);
    }
    for(int i = 0; i < N; i++)
           dst[i] = src[i] * 2;          
    return dst;
}

この場合、正しく使用したいのであれば、事前にメモリを割り当てる必要はありませんか?

さて、別のケース:

void dosomething(float *dst, const float *src, const int N)
{
    for(int i = 0; i < N; i++)
        dst[i] = src[i] * 2;
}

最後のケースでは、事前にメモリを割り当てる必要があります。だから私はそれを共有し、配列を返すための最良の方法はどれだろうと思っています. ライブラリまたはクラスのユーザーにより多くのセキュリティを提供するのはどれですか? どの方法が最も推奨されますか? なぜ?

4

3 に答える 3

2

より良い実践またはより良いアイデアは、実際に何をしようとしているのかによって異なります。

(POSIX)のような関数char *strdup(const char *s)は最初のケースのように実装され、文字列を引数として取り、同じ長さの別のメモリにメモリを割り当て、ソースを新しいメモリにコピーします。これは便利で、文字列のコピーにバッファーを割り当てるという一般的なアクションを手動で行う必要がありません。これは単純にmalloc、次にstrcpy/を呼び出すようなものだと考えることができmemcpyます。

次に、 のような関数を取得します。char *strcpy(char *dest, const char *src)これは、文字列のコピー先を制御できる 2 番目のケースのようなものです。このようにして、文字列を動的に割り当てられた、選択したものではないメモリにコピーする必要がなくなります。

最初の方法は、ある種の動的構造 (リスト、ツリーなど) を作成して初期化する必要がある場合に便利ですが、2 番目の方法でも十分であり、どのメモリが使用されているかを制御できます。ヒープ上で動的に割り当てられたメモリ、またはスタック上のローカル変数などを使用できます。

個人的には、どの変数を初期化するかをより詳細に制御でき、新しく作成されたメモリを使用する必要がないため、通常は 2 番目の方法を使用しmallocます (ローカル変数を初期化したい場合はどうすればよいでしょうか? )。malloc次に、新しく割り当てられたメモリを宛先として使用して、関数を呼び出し、次に関数を呼び出すラッパー関数をいつでも作成できます。

それは本当にあなたとあなたのデザイン、そしてあなたが達成しようとしていること次第です.正しい方法と間違った方法はありません.割り当てられたメモリを覚えている限り、問題はないはずです. どちらかが「安全」であるとは言えません。

于 2012-09-14T22:55:06.110 に答える
1

「これが他のものより優れている」という明確な定義はありません。私はこれらのことについて実際に考えることはなく、頭に浮かんだことを何でも実行します。これは、当面の問題に対するより「自然な」解決策である可能性があります。そして、途中で「悪い」ことが判明した場合... 幸いなことに、私たちは石板に彫刻してプログラミングしていません.

あなたの場合、ソフトウェアについて何も知らなければ、何も「気分が良くなる」ことはありません。これは実際には非常に一般的です。プログラミングで行うほとんどすべてのことは、さまざまな方法で行うことができます。多くの場合、個人的な好みや「最初に思いついた」というランダム以外に実際の違いはありません。

たとえば、2 番目のソリューションでは、呼び出し元が既存のメモリにコピーできます。これは、より大きなオブジェクトの一部である可能性があります。その一方で、彼は毎回目的地の記憶を提供しなければなりません。これは、複数の呼び出しに対して 1 つのメモリ ブロックのみを使用することで、割り当てを節約することも意味します。最初の解決策は、単純なケースでは少し便利に思えますが、その場合はユーザーを「ロック」します。常に新しいメモリ ブロックが割り当てられます。

于 2012-09-14T22:57:02.563 に答える
1

正解はありません。

C 言語は本質的に安全ではありません。つまり、コピーを作成してコピーを返す場合にのみデータを保護できます。したがって、発信者からオリジナルの実際の場所を隠します。

より重要なのは、共有データのメモリ割り当て解除をどのように処理するかです。これにより、通常、アプローチがより正確になります。

この例では、アクセスされている唯一のデータは、呼び出し元が既に渡した (そして既に所有している) データです。したがって、メモリを割り当て、データで何かを行い、割り当てられたメモリを呼び出し元に返すという事実は問題ありません。関数がどのように機能するかを文書化するだけです (strdup() が C 文字列で機能するように、呼び出し元は、返された非 NULL ポインターで free() を使用する責任があります)。

FWIW データを「共有」しません。呼び出し元は関数を呼び出して、代わりにデータに対して作業を行います。関数が返されると、それ以上のアクセスは発生しません。(関数によって) 保持されたメモリ ポインター (またはその他のデータ) があった場合、その状況を共有データとして説明するのが正しいでしょう。将来のある時点で、保持されたメモリポインタ(または他のデータ)が何らかの方法で利用される可能性があるためです。

于 2012-09-14T22:46:41.787 に答える