2014-02-07 23 views
0

該程序運行良好,除了最後一次免費,導致程序凍結。 當我註釋掉最後一個'空閒'時,它運行良好。錯誤釋放C **指針malloced在功能

該程序從一個字符串獲取所有子字符串並返回它。

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

char** getPrefixes(char* invoer); 

int main() 
{ 
    char buffer[100]; 
    char *input; 
    char **prefixes; 
    int counter = 0; 

    puts("Give string."); 
    fgets(buffer, 99, stdin); 
    fflush(stdin); 

    if (buffer[strlen(buffer) - 1] == '\n') 
     buffer[strlen(buffer) - 1] = '\0'; 

    input= (char*)malloc(strlen(buffer) + 1); 

    if (input == NULL) 
    { 
     puts("Error allocating memory."); 
     return; 
    } 

    strcpy(input, buffer); 

    prefixes = (char**) getPrefixes(input); 

    for (counter = strlen(input); counter > 0; counter--) 
    { 
     puts(prefixes[counter]); 
     free(prefixes[counter]); 
    } 

    free(input); 

    free(prefixes); 
} 

char** getPrefixes(char* input) 
{ 
    char** prefixes; 
    int counter; 

    prefixes = malloc(strlen(input) * sizeof(char*)); 

    if (prefixes == NULL) 
    { 
     puts("ELM."); 
     return NULL; 
    } 


    for (counter= strlen(input); counter> 0; counter--) 
    { 
     prefixes[counter] = (char*)malloc(counter + 1); 
     strcpy(prefixes[counter], input); 
     input++; 
    } 

    return prefixes; 
} 

在此先感謝!

+0

什麼是**出納員**?既沒有定義也沒有初始化。 –

+0

只是'免費'前綴'是不夠的,你也需要'免費'個人'前綴'[i]'。 – HAL

+0

'@MichaelWalz:'teller'是'counter'的荷蘭語,我把它翻譯成代碼之前粘貼它的一部分,但不是全部,就像'getPrefixes(char * input)'是'getPrefixes char * invoer)'higher up –

回答

1

您的程序凍結的原因很簡單:未定義的行爲+無效的返回值:_您的主函數返回void,而不是int:add return 0儘快!如果在執行編譯後的二進制文件後在控制檯中鍵入echo $?,則應看到0以外的其他編號。這是程序的退出代碼。 0以外的任何事物都意味着麻煩如果main沒有返回int,這是個壞消息。

下一頁:
發生未定義行爲在幾個地方,比如就在這裏:

prefixes = malloc(strlen(input) * sizeof(char*)); 
//allocate strlen(input) pointers, if input is 10 long => valid indexes == 0-9 
for (counter= strlen(input); counter> 0; teller--) 
{//teller doesn't exist, so I assume you meant "counter--" 
    prefixes[teller] = (char*)malloc(counter + 1);//first call prefixes[10] ==> out of bounds 
    strcpy(prefixes[counter], input);//risky, no zero-termination... use calloc + strncpy 
    input++; 
} 

然後,釋放內存的時候,你不釋放指針偏移@ 0,所以free(prefixes)調用無效:

for (counter = strlen(input); counter > 0; counter--) 
{//again 10 --> valid offsets are 9 -> 0 
    puts(prefixes[counter]); 
    free(prefixes[counter]); 
} 
free(prefixes);//wrong 

此外,有效索引均爲0及以上,你的循環條件(counter > 0)表示循環中斷,每當counter爲0呦U,在任何時候,被釋放的第一個指針數組中的一個索引/ offstet 0

寫您的循環跟大家會:

for (int i=0, size_t len = strlen(input); i<len; ++i) 
{ 
    printf("%d\n", i);//prints 0-9... 10 lines, all valid indexes 
} 

更改您的循環,並確保你」只使用有效的補償,你應該很好。使用strncpy,你仍然可以得到相同的結果之前:

for (int i=0;i<len;++i) 
{ 
    //or malloc(i+2), char is guaranteed to be 1 
    //I tend to use `calloc` to set all chars to 0 already, and ensure zero-termination 
    prefixes[i] = malloc((i+2)*sizeof(*prefixes[i])); 
    strncpy(prefixes[i], input, i+1);//max 1 - 10 chars are copied 
} 

如果我們將此到您的代碼,然後將其重新寫像這樣:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

char** getPrefixes(char* input); 

int main(void) 
{ 
    char *input; 
    char **prefixes; 
    int counter, i; 

    input= calloc(50,1); 
    if (input == NULL) 
    { 
     puts("Error allocating memory."); 
     return; 
    } 
    strcpy(input, "teststring"); 

    prefixes = getPrefixes(input); 
    counter = strlen(input); 
    for (i=0; i<counter;++i) 
    { 
     puts(prefixes[i]); 
     free(prefixes[i]); 
    } 

    free(input); 
    free(prefixes); 
    return 0; 
} 

char** getPrefixes(char* input) 
{ 
    int i, counter = strlen(input); 
    char** prefixes = malloc(counter * sizeof *prefixes); 

    if (prefixes == NULL) 
    { 
     puts("ELM."); 
     return NULL; 
    } 

    for (i=0; i<counter; ++i) 
    { 
     prefixes[i] = calloc(i + 2,sizeof *prefixes[i]); 
     strncpy(prefixes[i], input, i+1); 
    } 
    return prefixes; 
} 

我們得到的輸出是:

 
t 
te 
tes 
test 
tests 
testst 
teststr 
teststri 
teststrin 
teststring 

正如你可以看到自己

on this codepad

+0

非常感謝! –

1

爲指針分配內存指針:

char** cArray = (char**)malloc(N*sizeof(char*)); 

for(i=0;i<N;i++) 
    cArray[i] = (char*)malloc(M*sizeof(char)); 

去分配內存 - 以相反的順序:

for(i=0;i<N;i++) 
    free(cArray[i]); 
free(cArray) 

我希望這給你什麼是錯一點點的見解。

+1

你有一點,但這似乎不是'程序凍結'的答案 – HAL

+0

當你運行你的程序時,你在那裏有一些內存泄漏;這可能會導致您的環境凍結。我在VS中看到過類似的東西,但沒有凍結,而是需要很長時間才能完成(幾十秒) - 在什麼環境下運行它? – Pandrei

+0

@Pandrei:內存泄漏通常不會凍結。 –

1

您正在調用帶前綴[counter]的strcpy作爲目標。但是,根據(char *)的大小,每個前綴[counter]只分配了4/8個字節。(0128)。 )!空間

這樣做會破壞堆,這可能解釋爲什麼程序凍結。

+0

'(char *)malloc(counter + 1);'最壞的情況將會爲2分配足夠的內存字符。 'char *'的大小不會進入這個。真正的問題是:OP似乎不知道零索引數組和'strcpy'應該是'strncpy',當然 –

+0

你是對的我錯過了那條線 – thisisdog

+0

NP,因爲'input ++'應該避免溢出,只有零終止是一個問題 –