作者purpose (purpose)
看板C_and_CPP
標題Re: [問題] vc runtime error R6030
時間Tue Mar 5 11:59:48 2013
※ 引述《ddv70 (心神合一)》之銘言:
: 完整錯誤訊息:
: runtime error!
: program:C:(程式路徑)
: R6030
: -CRT not initialialized
原發問者提供的資訊不足。單純就錯誤訊息本身的含義來討論。
CRT not initialialized:
也就是 Microsoft C-RunTime 函式庫,未初始化。
可能是有執行 CRT,但過程中出錯,這種機率比較小;也可能是根本沒有執行到 CRT。
簡單的問題重現方式:
/* 檔案名稱:r6030.c */
#include <stdio.h>
#include <stdlib.h>
int main() {
int *ptr = 0;
ptr = malloc(1024);
ptr[0] = 1;
return 0;
}
啟動 Visual Studio 命令提示字元 (2010),執行
編譯連結指令 cl.exe r6030.c /Zi /link /entry:main
再啟動 r6030.exe:
runtime error R6030
- CRT not initialized
上述指令中 /Zi 只是為了輸出 *.pdb 檔來方便偵錯。而 /link /entry:main 是強迫更改
程式啟動後執行的第一個函數 (entry point),
從 mainCRTStartup 函數修改成 main 函數。
由 Visual Studio 附的 VC 原始碼 malloc.c 中,可知此函數:
__forceinline void * __cdecl
_heap_alloc (size_t size)
{
if (_crtheap == 0) {
_FF_MSGBANNER(); /* write run-time error banner */
_NMSG_WRITE(
_RT_CRT_NOTINIT); /* write message */
__crtExitProcess(255); /* normally _exit(255) */
}
return HeapAlloc(_crtheap, 0, size ? size : 1);
}
在檔案 rterr.h 及 cmsgs.h 可知有以下定義:
#define _RT_CRT_NOTINIT 30 /* CRT is not initialized */
#define _RT_CRT_NOTINIT_TXT L"R6030" EOL L"- CRT not initialized" EOL
在檔案 heapinit.c 可知有以下全域變數:
HANDLE _crtheap=NULL; /* NULL is 0 */
因為 VC 會連結 heapinit.c 與 r6030.c 這兩者的目的檔 (*.obj),
所以 _crtheap 必然初始值為 0,直到 CRT 的初始化正確進行才會變成非 0 值。
可是 r6030.exe 的入口點,是直接進入 main(),沒有先通過 mainCRTStartup() 函數,
就沒有做 CRT 初始化,所以 _crtheap 保留初始值。
所以當 r6030.exe 執行到 ptr = malloc(1024); 時,會接著進入 _heap_alloc(),
然後輸出錯誤訊息 "R6030\n- CRT not initialized\n",
然後執行 __crtExitProcess(255); 強制中斷程式運行,然後就沒有然後了。
----
補充:
上面的 return HeapAlloc(_crtheap, 0, size ? size : 1);
按照我上篇發文中討論的優先權議題,將等價於:
return HeapAlloc( _crtheap, 0, (size ? size : 1) );
/* 所以 malloc(0); 等價於 malloc(1); */
因為 _crtheap, 0, size 構成的是 expression
不能當作 ?: 的運算元I,所以運算元I 只會是 size。
要注意的是,在上面的 () 小括號中間出現的 , 其實不是真的 comma 運算子,
那只是分隔 HeapAlloc 的三個 arguments 用的逗號。
因為根據此文
http://en.wikipedia.org/wiki/Sequence_point
Note that a function call f(a,b,c) is not a use of the comma operator and
the order of evaluation for a, b, and c is unspecified.
如果 f() 中出現的逗號是 comma 運算子的話,會變成 a 要先運算完畢,把
副作用全部消除,才接著進行 b 的運算,事實上不是。
這部份有點算是特例,麻煩。應該不要在函數呼叫的小括號內:
(1) 使用 comma 運算子 /* 當然 comma 運算子本來就很少使用 */
(2) 放入任何會產生副作用的運算式,比如拿 a++ 當 arg1,又拿 a 當 arg2
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 124.8.130.63
推 ddv70:謝謝講解,但我原先這隻程式可以在桌機上正常執行 03/05 14:37
→ ddv70:但換到筆記型電腦後就不行,一執行exe檔就跳出上續訊息 03/05 14:38
→ ddv70:看完大大的講解我還是不太知道怎麼更改才好 03/05 14:38