3

C文字列をクリアしたり、割り当てられたメモリを解放したりする関数を作成するにはどうすればよいですか? 次のコードが機能しないのはなぜですか?

void freeStr(char** str) {
    free(*str);
}
int main() {
    char* str = "some string";
    freeStr(&str);
    printf("%s", str);
    return 0;
}
4

5 に答える 5

10

文字列リテラルが表す配列のメモリを解放したりクリアしたりすることはできません。

ただし、アクセスを失うには、アドレスを保存したポインターを変更するだけです。

str = NULL; // in main
// or
*str = NULL; // in freeStr
于 2012-09-05T22:58:12.187 に答える
4

割り当てた文字列はCONST_DATAセクション (変更不可) にあるため、free を呼び出すことはできません。

メモリのその部分はコンパイル時に割り当てられ、読み取り専用です。記憶のその部分はまだ保持されています"some string\0"

アセンブリのCONST_DATAセクションは、データ セグメント (DS) に似ており、コンパイル時に初期化されるグローバル変数と静的 (読み取り専用) 変数が含まれています。これらは実行時に変更され、実行中のプログラムに割り当てられたままになります。

于 2012-09-05T22:58:56.507 に答える
4

C FAQ - malloc セクションに目を通すと役立つ場合があります。

他の人が指摘しているように、通常はメモリの読み取り専用セクションに配置されるため、文字列リテラルを解放または変更することはできません。ただし、free()動的に割り当てられたメモリをクリアしたい場合は、次のようにします。

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

#define LENGTH  20

void freeStr(char **str)
{
    free( *str );
    *str = NULL;   
}

int main() {

    char *str = malloc( sizeof(char) * LENGTH);

    // clear that allocated memory
    memset( str, 0x00, LENGTH );

    // Put some text into the memory
    strncpy( str, "Some text", LENGTH-1 );

    printf("Before: %s\n", str);


    freeStr(&str);
    // string is now NULL and the memory is free.
    printf("After: %s\n", str);

    return 0;
}
于 2012-09-06T00:06:01.737 に答える
3

答えはかなり良いですが、見逃したり省略したりした点がいくつかあります。あなたの質問も少し曖昧です。

C文字列をクリアする場合は、それが指すメモリ空間をnullバイトで上書きします。、などfree()のヒープアロケータ関数の1つへの呼び出しを介して、ヒープアロケータによって割り当てられたC文字列のみを使用できます。malloc()calloc()realloc()

したがって、、malloc()または他のヒープ割り当て関数の1つを使用して文字列を割り当て、その文字列をコピーした場合は、を呼び出すことで文字列をクリアできmemset()ますが、それでも、free()そのメモリをヒープに解放するために呼び出す必要があります。 。

例えば:

char* strPtr = malloc(32); // allocate 32 bytes of storage off the heap
strcpy(strPtr, "test");    // copy a string into the newly allocated block on the heap
memset(strPtr, 0, 32);     // clear the allocated block
free(strPtr);              // return the allocated block to the heap

また、Cはブロックスコープを使用し、デフォルトのストレージクラスであるautoで宣言された配列は、そのブロックがスコープ外になるとスタックフレームからポップされるため、明示的に割り当てを解除する必要がないことに注意してください。

void foo() {
    char strArray[32];          // this is a stack allocation
    strcpy(strArray, "test");   // copy a string onto the stack
    return;                     // no call to free() required
}

最後に、さらに別の割り当て方法は静的です。宣言を使用する場合:

char* str = "literal string";

文字列「リテラル文字列」のスペースは、静的に割り当てられたセグメントにあり、決して書き込まれるべきではありません。一部のプラットフォームでは、そのメモリセグメントに書き込もうとすると、セグメンテーション違反が発生します。静的に割り当てられたメモリブロックは、それらがマップされているセグメントが書き込み可能であるという保証がないため、クリアしようとしないでください。

于 2012-09-05T23:10:25.500 に答える
2

http://en.cppreference.com/w/c/memory/free

void free( void* ptr );

malloc()、calloc()、または realloc() によって以前に割り当てられたスペースの割り当てを解除します。ptr が null ポインターの場合、関数は何もしません。

あなたの文字列は、これらの関数のいずれにも割り当てられていません。この通りだと思います。

void freeStr(char **str) {
    *str = NULL;
}
int main() {
    char* str = (char *)"some string";
    printf("Before: %s\n", str);
    freeStr(&str);
    printf("After: %s\n", str);
    return 0;
}
于 2012-09-05T23:02:54.060 に答える