2015-06-05 18 views
6

Ví dụ, ứng dụng này:Tại sao các ứng dụng CRT-miễn phí của tôi bị gián đoạn khi khởi động?

#define _WIN32_WINNT 0x0500 

#include <windows.h> 

int __stdcall NoCRTMain(void) 
{ 
    int result; 

    PWSTR lpCmdLine = GetCommandLine(); 

    for (;;) 
    { 
     if (*lpCmdLine == L'"') 
     { 
      lpCmdLine++; 
      for (;;) 
      { 
       if (*lpCmdLine == L'"') break; 
       if (*lpCmdLine == L'\0') break; 
       lpCmdLine++; 
      } 
     } 
     if (*lpCmdLine == L' ') break; 
     if (*lpCmdLine == L'\0') break; 
     lpCmdLine++; 
    } 

    while (*lpCmdLine == ' ') lpCmdLine++; 

    result = MessageBox(NULL, lpCmdLine, L"Scripting Engine", MB_OK | MB_SYSTEMMODAL); 

    if (result != IDOK) for (;;) Sleep(INFINITE); 

    ExitProcess(0); 
} 

xây dựng trong Visual Studio 2010 như một ứng dụng 64-bit không có thời gian chạy C, điều này hoạt động hoàn hảo - hầu hết thời gian. Đôi khi nó sẽ bắt đầu bị rơi khi khởi động vì không có lý do rõ ràng. Sự cố này xảy ra trước khi bất kỳ mã nào trong ứng dụng được chạy (xem bên dưới).

Khi sự cố xảy ra, nó chỉ xảy ra cho một trường hợp cụ thể của tệp thực thi, nghĩa là một tệp thi hành cụ thể. Bản sao giống hệt từng byte của tệp sẽ chạy bình thường. Vấn đề có thể (sẽ?) Biến mất khi máy tính được khởi động lại. Tôi đang chạy thử nghiệm để cố gắng tái tạo một cách đáng tin cậy vấn đề, để tôi có thể xác định các trường hợp mà vấn đề có thể xảy ra, ví dụ: chỉ khi Visual Studio được cài đặt? Chỉ khi chống vi rút được cài đặt? Nhưng cho đến nay tôi đã không có nhiều thành công trong việc tái tạo các vấn đề của bất kỳ thủ tục khác hơn là may mắn câm.

Hầu hết thời gian, gỡ lỗi cho thấy kernel32! BaseThreadInitThunk đang gọi địa chỉ không hợp lệ thay vì địa chỉ của NoCRTMain, mặc dù một số lần chạy gần đây đã thất bại sớm hơn, rõ ràng trong khi tải DLL.

Tôi tin rằng tôi đã theo dõi sự cố xuống ImageBase được đặt không đúng khi mô-đun được tải. Trên một ví dụ làm việc, một bãi chứa bộ nhớ tại 0x00D8 tương đối so với các mô-đun thực thi, cấu trúc _IMAGE_OPTIONAL_HEADER64 từ winnt.h:

00000001`3f5900d8 0b 02 0a 00 00 02 00 00 00 06 00 00 00 00 00 00 
00000001`3f5900e8 00 10 00 00 00 10 00 00 00 00 59 3f 01 00 00 00 

cho thấy ImageBase (tám byte cuối cùng) chứa địa chỉ của sự bắt đầu của mô-đun, trong trường hợp này 1`3f590000. Trên trường hợp không thành công, cùng một kết xuất bộ nhớ

00000001`3fc600d8 0b 02 0a 00 00 02 00 00 00 06 00 00 00 00 00 00 
00000001`3fc600e8 00 10 00 00 00 10 00 00 00 00 8f 3f 01 00 00 00 

cho thấy ImageBase, thay vì là 1`3fc60000 như mong đợi, là 1`3f8f0000.

Điều này dường như xảy ra trước điểm sớm nhất mà tại đó trình gỡ lỗi có thể kiểm tra quy trình, vì vậy tôi không chắc chắn cách tiếp tục. Có lẽ tôi cần phải làm hạt nhân gỡ lỗi? Tôi hiện đang có một máy ảo VMWare vSphere trưng bày vấn đề, và tôi có một ảnh chụp nhanh mà tôi có thể quay lại, vì vậy tôi có thể thử nghiệm.

Vì vậy:

  • không ai biết nguyên nhân của hành vi này, và quan trọng hơn, làm thế nào để ngăn chặn nó?

  • là cách hiểu của tôi về kết xuất bộ nhớ bị nhầm lẫn?

  • bất kỳ đề xuất gỡ rối/gỡ rối nào?

tùy chọn biên dịch:

tùy chọn
/Zi /nologo /W3 /WX- /O2 /Oi /GL /D "WIN32" /D "NDEBUG" /D "_WINDOWS" 
/D "_UNICODE" /D "UNICODE" /Gm- /EHsc /MT /GS- /Gy /fp:precise /Zc:wchar_t 
/Zc:forScope /Fp"x64\Release\sehalt.pch" /Fa"x64\Release\" /Fo"x64\Release\" 
/Fd"x64\Release\vc100.pdb" /Gd /errorReport:queue 

Linker:

/OUT:"C:\documents\code\w7lab-scripting\sehalt\x64\Release\sehalt.exe" 
/INCREMENTAL:NO /NOLOGO "kernel32.lib" "user32.lib" "gdi32.lib" 
"winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" 
"oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /NODEFAULTLIB 
/MANIFEST /ManifestFile:"x64\Release\sehalt.exe.intermediate.manifest" 
/ALLOWISOLATION /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG 
/PDB:"C:\documents\code\w7lab-scripting\sehalt\x64\Release\sehalt.pdb" 
/SUBSYSTEM:WINDOWS /OPT:REF /OPT:ICF 
/PGD:"C:\documents\code\w7lab-scripting\sehalt\x64\Release\sehalt.pgd" 
/LTCG /TLBID:1 /ENTRY:"NoCRTMain" /DYNAMICBASE /NXCOMPAT 
/MACHINE:X64 /ERRORREPORT:QUEUE 

PS: nhìn vào đó các ứng dụng của tôi được biết là đã thất bại theo cách này và đó không phải là, tôi nghi ngờ rằng sự cố chỉ xảy ra đối với các tệp thực thi có kích thước nhỏ hơn một trang (4096 byte).

+0

Re: _ "Một bản sao giống hệt từng byte của tệp sẽ chạy bình thường. Sự cố có thể (sẽ?) Biến mất khi máy tính được khởi động lại." _ Cho tôi biết rằng sự cố không nằm nghiêm trong mã nguồn của bạn, nhưng có lẽ với quá trình liên kết/tải. Có thể là một số thông tin là mất tích trong thực thi, dẫn bộ nạp của hệ điều hành phải "đoán" một số tham số (đôi khi không chính xác) và bộ nhớ đệm mà đoán. – stakx

+0

Làm cách nào để biên dịch và liên kết mã của bạn? Bạn có thể thêm dòng lệnh/cài đặt có liên quan vào câu hỏi của mình không? – stakx

+0

@stakx: cảm ơn; Tôi đã thêm các dòng lệnh trình biên dịch và trình liên kết. –

Trả lời

1

Một năm sau, tôi cuối cùng tự tin tuyên bố rằng đề xuất của Hans đã hoạt động hoàn hảo: nếu ứng dụng được xây dựng với các tùy chọn /DYNAMICBASE:NO/FIXED:YES, sự cố không xảy ra.

Các vấn đề liên quan