web-dev-qa-db-ja.com

メモリを割り当て、文字列をcに保存します

次のコードが機能しないのはなぜだろうと思っていました

int main(int argc, char **argv)
{
     char *test = (char*) malloc(12*sizeof(char));
     test = "testingonly";
     free(test);
}

それについて考えた後、私は最初にメモリ内の12文字にスペースを割り当てるが、次の行の割り当てがスタック上にchar配列を作成し、そのメモリアドレスがテストに渡されると仮定しました。したがって、free()は許可されていないスタック上のスペースを解放しようとします。あれは正しいですか?

それでは、ヒープに文字列を保存する正しい方法は何でしょうか?以下は一般的な方法ですか?

int main(int argc, char **argv)
{
     char *test = (char*) malloc(12*sizeof(char));
     strcpy(test, "testingonly");
     free(test);
}
21
pluckyDuck
char *test = (char*) malloc(12*sizeof(char));

        +-+-+-+-+-+-+-+-+-+-+-+-+
test--->|x|x|x|x|x|x|x|x|x|x|x|x|   (uninitialized memory, heap)
        +-+-+-+-+-+-+-+-+-+-+-+-+

test = "testingonly";

        +-+-+-+-+-+-+-+-+-+-+-+-+
test +  |x|x|x|x|x|x|x|x|x|x|x|x|
     |  +-+-+-+-+-+-+-+-+-+-+-+-+
     |  +-+-+-+-+-+-+-+-+-+-+-+-+
     +->|t|e|s|t|i|n|g|o|n|l|y|0|  
        +-+-+-+-+-+-+-+-+-+-+-+-+

free(test); // error, because test is no longer pointing to allocated space.

ポインタtestを変更する代わりに、文字列"testingonly"を割り当てられた場所にコピーする必要があります。 strcpyまたはstrdupを使用します。使用可能なメモリが不十分な場合、mallocstrdupなどの関数はNULLを返すため、チェックする必要があります。

char *test = (char*) malloc(12*sizeof(char));
strcpy(test, "testingonly");

        +-+-+-+-+-+-+-+-+-+-+-+-+
test--->|t|e|s|t|i|n|g|o|n|l|y|0|
        +-+-+-+-+-+-+-+-+-+-+-+-+

または

char *test = strdup("testingonly");

        +-+-+-+-+-+-+-+-+-+-+-+-+
test--->|t|e|s|t|i|n|g|o|n|l|y|0|
        +-+-+-+-+-+-+-+-+-+-+-+-+
65
Anders

あなたはすでにあなたの質問に答えました。基本的に、strcpyは文字列をコピーする適切な方法です。

8
dicaprio

最初のバージョンはスタック上に文字列を作成しませんが、割り当て後にfreeを許可しないことは正しいです。文字列リテラルは通常、メモリの定数/読み取り専用セクションに保存されます。割り当ては何もコピーせず、testがそのメモリ領域を指すようにします。解放できません。その文字列を変更することもできません。

2番目のコードは正しくて普通です。実装にそれがある場合は、strdupも調べてください。

5
Mat

さてあなたは正しいです。ここで、最初のコードを調べてみましょう。

char *test = (char*) malloc(12*sizeof(char));

上記のコードは問題ありません。

test = "testingonly";

ここでは、メモリリークにつながるポインタtestを変更しました。そして、解放しようとすると、実際に割り当てられたポインターではなく、1つの「testingonly」リテラルが指しているのを解放します。リテラルは、通常のシナリオではオーバーライドできない定数メモリを指します。

2番目のコードについては、リテラルが存在する場所からデータを明示的にコピーして、testが指しているヒープに正常に機能します。

2番目の点まではいstrcpyは通常の方法です。生バイトをコピーする場合、他の方法は「memcpy」です。

注:リテラルはスタックに保存されません。ただし、リテラルが保存されている場所は変更できません。

4
havexz

コード

#include <stdio.h>
int main(int argc, char **argv)
{
     char *test = (char*) malloc(12*sizeof(char));
     strcpy(test, "testingonly");
     printf("string is: %s\n",test);
     free(test);
     return 0;
}

働くでしょう

0
Anes

これはメモリを割り当てるためのものです:

char *string;
string = (char *) malloc(15);

これはデータを保存するためのものです:

strcpy(str, "kavitajain");
printf("String = %s,  Address = %u\n", str, str);
0
Kavita Jain