1

昨日、にメモリを割り当てる方法について同様の質問をしました。同じ問題 (一連の条件を含む) に関してもう 1 つ質問があります。二重解放を行わずに次の部分文字列を解放するにはどうすればよいでしょうか?freesub-string

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

struct st_ex {
    char product[16];
    float price;
};
struct st_temp {
    char *prod;
};

char *temp = NULL;

// from stackoverflow
char* substr( const char* source, size_t start, size_t end )
{
    char* dest = malloc( end - start + 1) ;
    memcpy( dest, &source[start], end - start ) ;
    dest[end - start] = 0 ;
    return dest ;
}

int main()
{
    struct st_ex structs[] = {{"mp3 player", 2.0f}, {"plasma tv", 20.0f},
                              {"notebook", 10.0f},  {"smartphone", 49.9f},
                              {"dvd player", 10.0f}, {"matches", 0.2f }};
    struct st_temp **temp_struct;

    size_t j, i;
    temp_struct = malloc(sizeof *temp_struct * 6);
    for (j = 0; j < 6; j++)
        temp_struct[j] = malloc(sizeof *temp_struct[j]);

    size_t structs_len = sizeof(structs) / sizeof(struct st_ex);

    // NOTE: that structs_len may vary in size - not just 6 
    for(i=0; i<structs_len; i++){
        if (i == 0)
            temp_struct[i]->prod = "+";
        else if(i == 1)
            temp_struct[i]->prod = "Bar";
        else if(i == 5)
            temp_struct[i]->prod = "Foo";
        else {
            temp = substr(structs[i].product, 0, 4);
            temp_struct[i]->prod = temp;
        }
    }
    for(i=0; i<6; i++ )
        printf("%s\n",temp_struct[i]->prod);

    for(i = 0; i < 6; i++ ){
        /* can I do something like this? */
        /*if (i != 0 || i != 1 || i != 5)*/
        free(temp_struct[i]->prod);
        free(temp_struct[i]);
    }
    free(temp_struct);
    return 0;
}
4

5 に答える 5

1

問題は、temp_struct[i]->prod解放できない引用符付き文字列 ("Bar") に設定する場合と、解放する必要がある substr 呼び出しの結果に設定する場合があることです。

最も簡単な解決策は、解放する必要がある文字列に常に設定することです。

  temp_struct[i]->prod = new_string("Bar");

どこ

char* new_string( const char* source )
{
    char* dest = malloc( strlen(source) + 1 ) ;
    strcpy(dest, source);        
    return dest ;
}

または、解放する必要があるかどうかを追跡する必要があります

 struct st_temp {
     char *prod;
     int prod_must_be_freed;
 };

prod_must_be_freed を 0 または 1 に設定し、解放する前に確認してください。

そして最後に、これらの構造体を直接いじるのではなく、関数を使用してこれらの構造体を操作することで、全体が改善されます。次にfree_st_temp(st_temp*)、prod を解放する必要があるかどうかをチェックしてから、構造体を解放することができます。あなたのループは

for(i = 0; i < 6; i++ ){    
    free_st_temp(temp_struct[i]);
}
于 2010-07-07T16:07:35.663 に答える
0

はい。 ただし、 that のコメントを外してif、 の条件を変更して、ではなくif結合する必要があります(そうしないと、常に true になります。すべての数値はゼロに等しくないか、1 に等しくありません!)&&||

0、1、および 5 以外のに格納された部分文字列はtemp_struct[i]->prod、 を使用して関数内で割り当てられたので、 でそれらの割り当てを解除することができます。isubstrmallocfree

同様に、各temp_struct要素は で割り当てられたmallocので、 で割り当てを解除できますし、そうすべきfreeです。

ダブルフリーがどこから来ると思うかわかりません。を呼び出すとfree(tmp_struct[i])、指しているメモリtmp_struct[i]->prodも解放されると思いますか?そうではありません。ポインターを含む構造体へのポインターを解放すると、構造体のポインター自体のメモリーは (構造体の一部であるため) 解放されますが、それらのポインターが指すメモリーは解放されず、個別に解放する必要があります (構造の外部にあるため)。状態の間違いは別として、ifあなたが書いた方法が正しい方法です。

于 2010-07-07T16:03:36.570 に答える
0

部分文字列は余分なメモリを消費しません。これらは、既存の文字列の一部へのポインタです。

于 2010-07-07T16:04:45.520 に答える
0

はい、あなたsubstrが で部分文字列のメモリを割り当てていることを考えると、それを使い終わったとき、そのメモリにはmalloc合理的です (本当に必要です) 。freeそうは言っても、あなたが今やっているやり方は非常に壊れやすく、エラーが発生しやすいと思います (控えめに言っても)。選択肢がある場合は、すべてprodメンバーに同じ方法で文字列を割り当てます。すべてを静的に割り当てることができない場合は、すべてを動的に割り当てるので、構造体を解放するときに行うことができますとても均一に。prod添字が動的に割り当てられた場合に限り、添字を自由に一致させておくことを保証しようとすると、実際には問題が発生します。

于 2010-07-07T16:06:46.330 に答える
0

追加の問題があります。あなたがするとき あなたはtemp_struct[i]->prod = "Bar";prodにconst char*を割り当てています。そのポインターは解放できません (最も可能性の高い結果はクラッシュです)。したがって、prod が malloc から取得した動的メモリまたは定数文字列リテラルのいずれかを指すことができるように、コードをこのように設定したい場合は、それがどちらであるかを追跡し、動的メモリのみを解放する必要があります。 .

あなたのコメントの状態は技術的には機能しますが、非常に貧弱な形になります. 最善の方法は、同じポインター内で文字列型を混在させたり一致させたりしないことです。ただし、そのようにすることを主張する場合は、構造体に別の変数を追加して、prod を解放する必要がある場合は true に設定し、解放しない場合は false に設定することをお勧めします。

于 2010-07-07T16:07:37.077 に答える