2010-08-29 86 views
7

在我的項目中,我有一個從整數(使用strcat)創建一個字符串並將其寫入文件的方法。不幸的是,它確實有內存泄漏。在跟蹤泄漏時,我將代碼簡化爲以下內容。我似乎無法找到甚至修復它。這是代碼:此代碼中的內存泄漏以及如何修復它?

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
int main(int argc, char* argv[]) 
{ 
char* output = "\0"; 
int counter = 5; 
    while(counter > 0) 
    { 
     char buffer[20]; 
     sprintf(buffer, "%u", counter); 
     char* temp; 
     temp = malloc((strlen(output) + strlen(buffer) + 1)); 
     strcpy(temp, buffer); 
     strcat(temp, output); 
     char* oldmemory = output; 
     output = temp; 
     free(oldmemory); 
     counter--; 
    } 
printf("output: %s\n", output); 
free(output); 
return 0; 
} 

Valgrind的回報:

==7125== Memcheck, a memory error detector 
==7125== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al. 
==7125== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info 
==7125== Command: ./foo 
==7125== Parent PID: 4455 
==7125== 
==7125== Invalid free()/delete/delete[] 
==7125== at 0x4024B3A: free (vg_replace_malloc.c:366) 
==7125== by 0x8048662: main (foo.c:20) 
==7125== Address 0x8048780 is not stack'd, malloc'd or (recently) free'd 
==7125== 
==7125== 
==7125== HEAP SUMMARY: 
==7125==  in use at exit: 0 bytes in 0 blocks 
==7125== total heap usage: 5 allocs, 6 frees, 20 bytes allocated 
==7125== 
==7125== All heap blocks were freed -- no leaks are possible 
==7125== 
==7125== For counts of detected and suppressed errors, rerun with: -v 
==7125== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 15 from 8) 

哪裏是內存泄漏,如何解決呢?

回答

9
#include <stdio.h> 
#include <stdlib.h> 
int main(int argc, char* argv[]) 
{ 
char* output = "\0"; 

字符串文字是'\ 0'自動終止,您不需要添加它。

int counter = 5; 
    while(counter > 0) 
    { 
     char buffer[20]; 
     sprintf(buffer, "%u", counter); 
     char* temp; 
     temp = malloc((strlen(output) + strlen(buffer) + 1)); 
     strcpy(temp, buffer); 
     strcat(temp, output); 
     char* oldmemory = output; 
     output = temp; 
     free(oldmemory); 

第一次這個free()被調用時,它的釋放輸出的初始值,它是一個指向字符串文字"\0"。在從*alloc()NULL返回的有效指針以外的任何其他位置調用free()是未定義的行爲。

 counter--; 
    } 
printf("output: %s\n", output); 
free(output); 
return 0; 
} 

的valgrind報告:

==7125== Invalid free()/delete/delete[] 
==7125== at 0x4024B3A: free (vg_replace_malloc.c:366) 
==7125== by 0x8048662: main (foo.c:20) 
==7125== Address 0x8048780 is not stack'd, malloc'd or (recently) free'd 

這不是一個內存泄漏;這是一個無效的free()

+0

+1有明確的解釋。 – RBerteig 2010-08-29 22:27:43

3

您的應用崩潰嘗試釋放(「\ 0」)。 (注意,如果你想要一個空字符串,「」就夠了,「\ 0」實際上是字符串\ 0 \ 0。

而不是使用malloc和strcpy,看看realloc,它做你想做的一切但更好:)但你最有可能想建立你的字符串正向(計數器= 0;計數器< 5;計數++),而不是倒退

+3

除了失敗的realloc返回NULL,所以你必須注意在你執行'p = realloc(p,new_size)'的情況下的泄漏。 – 2010-08-29 14:16:42

+0

@Roger:失敗'realloc'可能意味着程序必須優雅地終止。不要認爲內存泄漏是非常重要的。 – 2010-08-29 14:48:33

+0

它不難用'realloc'來捕捉潛在的泄漏,只需保留原始指針的副本,以便它可以被釋放。或者,假設失敗的「realloc」意味着世界的盡頭,並且剛剛退出。我個人喜歡使用assert()來進行檢查,因爲它確保退出是一個顯着的失敗。 – RBerteig 2010-08-29 22:27:11

4

您的代碼已損壞。第一次通過時,您將oldmemory設置爲輸出,其中輸出指向未在堆中分配的內存。之後,你試圖釋放這個內存。這會產生關於釋放未通過malloc分配的內存的valgrind錯誤。因此,您分配的原始內存永遠不會被釋放。

+0

我認爲他/她知道它已經壞了。沒有必要對此表示粗魯。 – 2012-12-06 21:45:13

+0

WTF?我寫的是如何粗魯?我認爲你的靈敏度檢測器設置得有點過高。或者我是粗魯的指出這一點。也許你已經知道了。 – sizzzzlerz 2012-12-06 22:11:31

+0

洛爾不需要隨機開始投票我的問題,婊子 – 2012-12-06 22:36:24

1

如果你想使用這種算法,用於對應該使用malloc分配什麼輸出點,正是如此的初始空間:

char *output = malloc(1); 
if(!output) { /* handle error */ } 
output[0] = '\0'; 
... rest of code as is ... 

字符串文字不與malloc分配的,因此不能free 'ed,這是你問題的根源。