1

そこで、未知の量の文字列を受け取り、それらを文字列の配列に追加するこの関数を作成しました。

char **receiveCode(int socket){
    int line = 0;
    size_t lines = 1;
    size_t size = 1;
    char** code = malloc(sizeof(char)*size);

    while(1){
        package_struct *aPackage = receivePackage(socket);
        if(aPackage->type=='F'){break;}
        size = size + aPackage->size;
        code = realloc(code, size);
        code[line] = malloc(sizeof(char)*aPackage->size);
        strcpy(code[line],aPackage->package);
        line++;
        lines++;
        free(aPackage);
    }
    code = realloc(code, size + 2);
    code[line] = malloc(sizeof(char)*3);
    code[lines]=NULL;
    return code;
}

このコードを実行すると、次のエラーが表示されることがあります

* glibc が検出されました./pp: realloc(): 次のサイズが無効です: 0x00007f0f88001220 * *

Valgrind によれば、これはその関数で発生します。

おそらく、malloc と realloc を使いすぎているのでしょう...よくわかりません。

4

3 に答える 3

3

これは、次の配列を割り当てることだと思いchar*ます:

code = realloc(code, size);

する必要があります

code = realloc(code, size * sizeof(char*));
// and this one too
code = realloc(code, size + 2 * sizeof(char*));

また、これは必要ありません:

char** code = malloc(sizeof(char)*size);

あなたが呼び出す場合、realloc(NULL, size)それはmalloc(size)

size_t size = 0;
char** code = NULL;
...
code = realloc(code, size * sizeof(char*));

注:lines私には役に立たないようです。実際、最後の2行で、割り当てたばかりのメモリを上書きしますline==lines

于 2012-11-21T20:16:31.317 に答える
3

問題はこれだと思います:

char** code = malloc(sizeof(char)*size);

内部ではchar *なくcharsizeof()

char** code = malloc(sizeof(char*)*size);

codeは文字列へのポインタであるため、ポインタにメモリを割り当てます。char*

また、同様の問題がありますrealloc

于 2012-11-21T20:15:02.527 に答える
1

strdup()テキストの新しい行ごとにメモリの割り当てを簡素化するために使用するバージョンを次に示します。また、メモリ割り当て関数の「x」バージョンを使用して、メモリ不足のエラー処理を簡素化します (非標準であっても、やや一般的なイディオムです)。

したがって、実際に残っているすべての複雑さ (最終的にはそれほど多くはありません) は、文字列ポインターの配列の増加を管理することです。これにより、各文字列の処理とポインターの配列の処理を分離しやすくなると思います。元のコードでは、これら 2 つの領域が混乱していました。

// these variants allocate memory, but abort program on failure
//  for simplified error handling - you may need different
//  error handling, but often this is enough
//
//  Also, your platform may or may not already have these functions
//      simplified versions are in the example.

void* xmalloc( size_t size);
void* xrealloc(void* ptr, size_t size);
char* xstrdup(char const* s);


char** receiveCode(int socket){
    size_t lines = 0;
    char** code = xmalloc( (lines + 1) * sizeof(*code));

    *code = NULL;

    while(1){
        package_struct *aPackage = receivePackage(socket);
        if(aPackage->type=='F') {
            free(aPackage); // not 100% sure if this should happen here or not.
                            // Is a `package_struct` with type 'F' dynamically
                            // allocated or is a pointer to a static sentinel 
                            // returned in this case?
            break;
        }


        // why use `aPackage->size` when you use `strcpy()` to
        //  copy the string anyway? Just let `strdup()` handle the details
        //
        // If the string in the `pckage_struct` isn't really null terminated, 
        // then use `xstrndup(aPackage->package, aPackage->size);` or something
        // similar.

        char* line = xstrdup(aPackage->package);
        ++lines;

        // add another pointer to the `code` array
        code = xrealloc(code, (lines + 1) * sizeof(*code));
        code[lines-1] = line;
        code[lines] = NULL;

        free(aPackage);
    }

    return code;
}


void* xmalloc(size_t size)
{
    void* tmp = malloc(size);

    if (!tmp) {
        fprintf(stderr, "%s\n", "failed to allocate memory.\n";
        exit(EXIT_FAILURE);
    }

    return tmp;
}

void* xrealloc(void *ptr, size_t size)
{
    void* tmp = realloc(ptr, size);

    if (!tmp) {
        fprintf(stderr, "%s\n", "failed to allocate memory.\n";
        exit(EXIT_FAILURE);
    }

    return tmp;
}


char* xstrdup(char const* s)
{
    char* tmp = strdup(s);

    if (!tmp) {
        fprintf(stderr, "%s\n", "failed to allocate memory.\n";
        exit(EXIT_FAILURE);
    }

    return tmp;
}

aPackage->packageまた、文字列ポインタなのか、文字列データを保持する実際の場所なのかchar[](つまり、/ ?&aPackage->packageに渡す必要があるのか​​) を明確にする必要があると思います。それが本当にポインターである場合、解放する前に解放する必要がありますか?strcpy()xstrdup()aPackage

于 2012-11-21T21:21:35.247 に答える