重新分配一个字符串数组

时间:2012-11-21 20:10:01

标签: c malloc valgrind realloc

所以我创建了这个接收未知数量的字符串并将它们添加到字符串数组中的函数。

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的说法,这个功能发生了。

可能我使用太多的mallocs和reallocs ......但不确定。

3 个答案:

答案 0 :(得分:3)

我认为问题是:

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

char *

中应该是char而不是sizeof()
char** code = malloc(sizeof(char*)*size);

由于code是指向字符串的指针,因此为指针char*分配内存

realloc

中也存在同样的问题

答案 1 :(得分: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对我来说似乎没用,实际上在最后两行中你覆盖了自line==lines以来刚刚分配的内存

答案 2 :(得分:1)

这是一个使用strdup()来简化每个新文本行的内存分配的版本。它还使用'x'版本的内存分配函数来简化内存不足错误处理(即使非标准也是一种常见的习惯用法)。

因此,真正保留的所有复杂性(最终不会太多)是在管理字符串指针数组的增长。我认为这使得处理每个字符串与处理指针数组更容易分开。原始代码使这两个领域混淆不清。

// 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之前被释放吗?