2012-11-21 88 views
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和reallocs ...不知道。

+3

下面有很多正確的答案:側欄,打破'ptr = realloc(ptr,size)'的習慣,除非你真的不在乎重新分配失敗是否會泄露你先前分配的內存。分配給temp並僅在成功時覆蓋prev指針。 – WhozCraig

回答

3

我認爲這個問題是這樣的:

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

應該char *,而不是charsizeof()

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

由於code是一個指向字符串,以便爲指針分配內存是char*

在也有同樣的問題

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

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之前被釋放嗎?