0

メインでダブルポインターを宣言し、このようにメモリを割り当てました

char  **group_name;
group_name = realloc( NULL, 1);
group_name[0] = realloc(NULL ,20);

この配列を関数に渡しました。

group_count(object, count, group_name);

realloc を使用します。最初の 4 つの再割り当てが完了するまで問題なく動作しますが、5 番目でエラーが発生します。

libc detected *** ./textfileread.exe:  realloc(): invalid next size: 0x08643008

int group_count(struct friends obj[], char cn, char **grp_nm)
{
    int i=0,j=0;
    int grp_cn=0;
    char check=0;
    strcpy(grp_nm[0],obj[0].group);
    grp_cn++;
    grp_count++;

    for(i=1;i<cn;i++) {
        for(j=0;j<grp_cn;j++) {
            if(strcmp(grp_nm[j],obj[i].group)==0)
                check=1;
        }
        if(check==0) {  
            grp_cn++;
            grp_count++;
            printf("\t%d\n",grp_cn);
            grp_nm = realloc( grp_nm, grp_cn);   //at grp_cn=5 allocation gives error
            printf("\t%d\n",grp_nm);
            if(grp_nm == NULL) printf("\t%d\n",grp_cn);  // this 'if' didnt run, means no NULL return
            grp_nm[grp_cn-1] = realloc(NULL ,20);
            strcpy(grp_nm[grp_cn-1],obj[i].group);
        }
    check=0;
    }
}

printf("\t%d\n",grp_nm) の出力; この後、再割り当ての 5 回目の反復で

2
140783624
3
140783624
4
140783624
5

*** glibc detected *** ./textfileread.exe: realloc(): invalid next size: 0x099c8008        ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x6b961)[0x17b961]
lib/i386-linux-gnu/libc.so.6(+0x6f1ad)[0x17f1ad]
/lib/i386-linux-gnu/libc.so.6(realloc+0xe9)[0x180579]
./textfileread.exe[0x804934e]
./textfileread.exe[0x8048b42]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xe7)[0x126e37]
./textfileread.exe[0x8048751]
======= Memory map: ========
00110000-0026a000 r-xp 00000000 08:02 1570626    /lib/i386-linux-gnu/libc-2.13.so

画面の出力で5の後、アドレスは4の後に表示されたように表示されるはずですが、そうではなかったので、なぜ5でエラーが発生するのですか?

4

4 に答える 4

2

問題の核心は、mallocが新しく割り当てられたブロックと一緒に設定する簿記ポインターに損傷を与えている可能性があります。その「ブロック」をreallocに戻すと、破損したポインタを使用して、空きゾーンやその他の同様のアクティビティにメモリを再挿入しようとします。

「なぜ4ではなく5」...おそらく、reallocがその前に以前に返されたブロックの1つを使用する必要がなかったためです(たとえば、ブロックが実際に要求したよりも大きく、reallocが再割り当てしなくても問題ないと考えているため)いくつかのメモリ)。malloc / freeは複雑なソフトウェアであり、誤用するとカオス的な動作を示す場合があります。

于 2012-08-13T09:48:19.540 に答える
1

realloc初期割り当てに使用する理由

ともかく...

char  **group_name;
group_name = realloc( NULL, 1);
// group_name is now pointing to 1 byte of dynamically allocated memory
group_name[0] = realloc(NULL ,20);
// Whoops. Did we just write 4(or more bytes) into our 1 allocated byte?

メソッド内にも同じ問題があると思います。

于 2012-08-13T05:35:37.173 に答える
0

おそらく問題は、割り当て時に間違ったサイズを使用したためです。

char  **group_name;
group_name = realloc( NULL, 1);

ただし、achar **は1 バイトではなく、4 または 8 のいずれかです (32 ビットまたは 64 ビットのプラットフォームを使用しているかによって異なります)。代わりに次のsizeof演算子を使用します。

group_name = realloc( NULL, sizeof *group_name);

そして後で再割り当てするとき:

grp_nm = realloc( grp_nm, grp_cn * sizeof *grp_nm);
于 2012-08-13T05:53:27.390 に答える
0

ありがとう。それは役に立ちました。

   group_name = realloc( NULL, sizeof *group_name); 
    grp_nm = realloc( grp_nm, grp_cn * sizeof *grp_nm); 

そのlibcエラーが終了した後。しかし、配列がサブルーチン、つまり main() に取り込まれた後、値を読み取ることができない場合があります。しかし、サブルーチン grp_nm[3] では、サブルーチンで配列 group_name へのポインターを渡したので、非常によく表示されました。私が見つけた理由は、再割り当て中に残りのメモリと競合すると、配列全体が新しい場所に再定義され、配列へのポインターが変更されるためです。たとえば、サブルーチンに渡した後、メインの group_name=0x5689F0 で、最初の再割り当て grp_nm=0x5689F0 で 2 番目の再割り当て grp_nm=0x5689F0

メモリの競合による再割り当ての後、配列grp_nm の位置が変更され、0x345FF1 になります。だから私はこのようなサブルーチンからこのポインタを返さなければなりません

     group_name=group_count(object, count, group_name);     

ポインタが変更された場合、今すぐ更新されるように group_name=0x345FF1

于 2012-08-16T18:54:12.803 に答える