我還沒有再次關於C的(ANSI-C通過VS2012編譯)的運作C:動態字符陣列崩潰堆
我重構一個獨立的程序(.EXE)到一個.dll問題。到目前爲止,這工作得很好,但當涉及到日誌記錄時,我偶然發現了問題。讓我解釋一下:
原始程序 - 運行時 - 寫了一個日誌文件並將信息打印到屏幕上。由於我的DLL是要在一個Web服務器上運行,被許多人同時訪問有
- 沒有真正的機會,妥善處理日誌文件(及後他們清理)
- 沒有控制檯窗口任何人看見
因此,我的目標是將所有可以放在日誌文件或屏幕上的所有內容寫入字符串變量(我知道C中沒有字符串),然後我可以通過請求給調用者(也是一個DLL,但用C#編寫)。
由於用C這樣的事情是不可能的:
char z88rlog;
z88rlog="First log-entry\n";
z88rlog+="Second log-entry\n";
我有兩個可能性:
char z88rlog[REALLY_HUGE];
- 動態分配內存
在我心中的第一方式是被忽略,因爲:
- 記憶的潛在浪費是相當巨大的
- 我可能仍然需要更多的內存比
REALLY_HUGE
,從而創造一個緩衝區溢出
這給我留下了第二種方式。我已經做了一些工作,並提出了兩種解決方案,其中任何一種都無法正常工作。
/* Solution 1 */
void logpr(char* tmpstr)
{
extern char *z88rlog;
if (z88rlog==NULL)
{
z88rlog=malloc(strlen(tmpstr)+1);
strcpy(z88rlog,tmpstr);
}
else
{
z88rlog=realloc(z88rlog,strlen(z88rlog)+strlen(tmpstr));
z88rlog=strcat(z88rlog,tmpstr);
}
}
在溶液1(相當於解決方案2,你會發現)我穿過char tmpstr[255];
我的新的日誌條目。我的「日誌文件」z88rlog
是全局聲明的,所以我需要extern
來訪問它。然後我檢查內存是否已分配給z88rlog
。如果沒有,我將記錄分配給我的日誌條目的大小(我的\0
爲+1),並將tmpstr
的內容複製到z88rlog
。如果是,我重新分配內存z88rlog
它的大小+的長度爲tmpstr
(+1)。然後使用strcat
加入兩個「字符串」。使用斷點的直接窗口我obtainded以下的輸出:
z88rlog
0x00000000 <Schlechtes Ptr>
z88rlog
0x0059ef80 "start Z88R version 14OS"
z88rlog
0x0059ef80 "start Z88R version 14OS
opening file Z88.DYNÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍýýýý««««««««þîþîþîþ"
它顯示logpr連續三個電話(斷點前strcpy
/strcat
)。最後的難以區分的亂碼是由內存分配引起的。之後,VS發出一條錯誤消息,指出調試器在realloc.c
中設置了一個斷點。因爲這顯然是行不通的我炮製我的妙解2:
/* Solution 2 */
void logpr(char* tmpstr)
{
extern char *z88rlog;
char *z88rlogtmp;
if (z88rlog==NULL)
{
z88rlog=malloc(strlen(tmpstr)+1);
strcpy(z88rlog,tmpstr);
}
else
{
z88rlogtmp=malloc(strlen(z88rlog)+strlen(tmpstr+1));
z88rlogtmp=strcat(z88rlog,tmpstr);
free(z88rlog);
z88rlog=malloc(strlen(z88rlogtmp)+1);
memcpy(z88rlog,z88rlogtmp,strlen(z88rlogtmp)+1);
free(z88rlogtmp);
}
}
這裏我的目標是創造我的日誌文件的副本,釋放原件的記憶在新的大小創造的原新內存並將內容複製回來。並且不要忘記釋放臨時副本,因爲它是通過malloc分配的。當它達到free
時,它會立即崩潰,並再次告訴我堆可能被破壞。
因此,讓我們暫時免費評論。這種方法的效果更好 - 對我來說非常舒服 - 但是在建立日誌字符串時,並不是所有來自z88rlogtmp
的字符都被複制。但一切仍然正常。直到突然間我又告訴堆可能會被打破,調試器把一個斷點在_heap_alloc (size_t size)
in malloc.c
size
末有 - 根據調試器 - 的1041
所以此值我有2個(或3)的方式我想實現這種「字符串增長」,但沒有任何作用。給我的大小的錯誤可能會導致陣列變大的結論?我希望我解釋清楚我想做什麼,有人可以幫助我:-)提前致謝!
諷刺也許我應該去買一些新的電腦堆。它適合RAM插槽嗎?任何人都可以推薦一個好品牌嗎? 反諷
太棒了!修復我的'realloc'的確有竅門!修復'strlen(tmpstr + 1)'然而沒有。這兩種解決方案如此不同? – lhiapgpeonk
@lhiapgpeonk是的,這兩種解決方案是不一樣的,因爲我已經在我的更新的答案中指出。 –