เมื่อฉันพยายามสร้างโปรแกรมโดยใช้Eclipse CDT
ฉันจะได้รับสิ่งต่อไปนี้:
/mingw/lib/libmingw32.a(main.o):main.c:(.text+0x106): การอ้างอิงที่ไม่ได้กำหนดถึง `WinMain @ 16
ทำไมถึงเป็นเช่นนั้น? และฉันจะแก้ปัญหานี้ได้อย่างไร
เมื่อฉันพยายามสร้างโปรแกรมโดยใช้Eclipse CDT
ฉันจะได้รับสิ่งต่อไปนี้:
/mingw/lib/libmingw32.a(main.o):main.c:(.text+0x106): การอ้างอิงที่ไม่ได้กำหนดถึง `WinMain @ 16
ทำไมถึงเป็นเช่นนั้น? และฉันจะแก้ปัญหานี้ได้อย่างไร
คำตอบ:
พิจารณาโปรแกรมระดับ Windows API ต่อไปนี้:
#define NOMINMAX
#include <windows.h>
int main()
{
MessageBox( 0, "Blah blah...", "My Windows app!", MB_SETFOREGROUND );
}
ตอนนี้มาสร้างโดยใช้ GNU toolchain (เช่น g ++) ไม่มีตัวเลือกพิเศษ นี่gnuc
เป็นเพียงไฟล์แบตช์ที่ฉันใช้สำหรับสิ่งนั้น มีเพียงตัวเลือกเพื่อทำให้ g ++ เป็นมาตรฐานมากขึ้น:
C: \ test> gnuc x.cpp C: \ test> objdump -x a.exe | findstr / i "^ ระบบย่อย" ระบบย่อย 00000003 (Windows CUI) C: \ test> _
ซึ่งหมายความว่าโดยดีฟอลต์ตัวเชื่อมสร้างระบบย่อยคอนโซลที่เรียกใช้งานได้ ระบบย่อยค่าในส่วนหัวของแฟ้มบอกสิ่งที่ให้บริการของ Windows โปรแกรมต้อง ในกรณีนี้กับระบบคอนโซลโปรแกรมต้องใช้หน้าต่างคอนโซล
นอกจากนี้ยังทำให้ตัวแปลคำสั่งรอให้โปรแกรมทำงานให้เสร็จสมบูรณ์
ทีนี้มาสร้างด้วยระบบย่อย GUIซึ่งหมายความว่าโปรแกรมไม่ต้องการหน้าต่างคอนโซล:
C: \ test> gnuc x.cpp -mwindows C: \ test> objdump -x a.exe | findstr / i "^ ระบบย่อย" ระบบย่อย 00000002 (Windows GUI) C: \ test> _
หวังว่าจะเป็นอย่างนั้นแม้ว่า-mwindows
แฟล็กจะเป็นเพียงเอกสารกึ่งเอกสาร
การสร้างโดยไม่มีแฟล็กกึ่งเอกสารนั้นจะต้องบอกผู้เชื่อมโยงให้มากขึ้นว่าระบบย่อยต้องการค่าใดและโดยทั่วไปแล้วไลบรารีการนำเข้า Windows API บางไลบรารีจะต้องระบุอย่างชัดเจน:
C: \ test> gnuc x.cpp -Wl, -subsystem, windows C: \ test> objdump -x a.exe | findstr / i "^ ระบบย่อย" ระบบย่อย 00000002 (Windows GUI) C: \ test> _
มันใช้งานได้ดีด้วย GNU toolchain
แต่ Microsoft toolchain เช่น Visual C ++ ล่ะ?
การสร้างเป็นระบบย่อยคอนโซลที่เรียกใช้งานได้ดี:
C: \ test> msvc x.cpp user32.lib x.cpp C: \ test> dumpbin / headers x.exe | ค้นหา / i "ระบบย่อย" | ค้นหา / i "Windows" 3 ระบบย่อย (Windows CUI) C: \ test> _
อย่างไรก็ตามด้วยการสร้าง toolchain ของ Microsoft เนื่องจากระบบย่อย GUI ไม่ทำงานตามค่าเริ่มต้น:
C: \ test> msvc x.cpp user32.lib / link / ระบบย่อย: windows x.cpp LIBCMT.lib (wincrt0.obj): ข้อผิดพลาด LNK2019: สัญลักษณ์ภายนอกที่ไม่ได้รับการแก้ไข _WinMain @ 16 ที่อ้างถึงในฟังก์ชัน ___tmainCRTStartu น x.exe: ข้อผิดพลาดร้ายแรง LNK1120: 1 ภายนอกที่ไม่ได้รับการแก้ไข C: \ test> _
เทคนิคนี้เป็นเพราะลิงเกอร์ไมโครซอฟท์เป็นที่ไม่ได้มาตรฐานโดยเริ่มต้นสำหรับ GUI ระบบย่อย โดยค่าเริ่มต้นเมื่อระบบย่อยคือ GUI แล้วลิงเกอร์ไมโครซอฟท์ใช้ห้องสมุดรันไทม์จุดเข้าฟังก์ชั่นที่มีการเรียกใช้รหัสเครื่องเริ่มต้นที่เรียกwinMainCRTStartup
ว่าไมโครซอฟท์เรียกร้องที่ไม่ได้มาตรฐานแทนมาตรฐานWinMain
main
ไม่มีเรื่องใหญ่ที่จะแก้ไขได้
สิ่งที่คุณต้องทำคือบอกผู้เชื่อมโยงของ Microsoft ว่าจะใช้จุดเข้าใช้งานmainCRTStartup
ใดซึ่งเรียกว่ามาตรฐานmain
:
C: \ test> msvc x.cpp user32.lib / link / ระบบย่อย: windows / entry: mainCRTStartup x.cpp C: \ test> dumpbin / headers x.exe | ค้นหา / i "ระบบย่อย" | ค้นหา / i "Windows" 2 ระบบย่อย (Windows GUI) C: \ test> _
ไม่มีปัญหา แต่น่าเบื่อมาก และมีความลับและซ่อนอยู่ทำให้โปรแกรมเมอร์ Windows ส่วนใหญ่ซึ่งส่วนใหญ่ใช้เฉพาะเครื่องมือที่ไม่ได้มาตรฐานโดยค่าเริ่มต้นของ Microsoft ไม่รู้ด้วยซ้ำและเข้าใจผิดคิดว่าโปรแกรมระบบย่อย Windows GUI“ ต้อง” ไม่ได้มาตรฐานWinMain
แทนที่จะเป็นมาตรฐานmain
. ในการส่งผ่าน C ++ 0x Microsoft จะมีปัญหากับสิ่งนี้เนื่องจากคอมไพเลอร์จะต้องโฆษณาว่าเป็นแบบอิสระหรือโฮสต์ (เมื่อโฮสต์ต้องรองรับมาตรฐานmain
)
อย่างไรก็ตามนั่นเป็นเหตุผลที่ g ++ สามารถบ่นว่าWinMain
หายไป: มันเป็นฟังก์ชั่นการเริ่มต้นที่ไม่ได้มาตรฐานโง่ ๆ ที่เครื่องมือของ Microsoft ต้องการโดยค่าเริ่มต้นสำหรับโปรแกรมระบบย่อย GUI
แต่อย่างที่คุณเห็นด้านบน g ++ ไม่มีปัญหากับมาตรฐานmain
แม้แต่กับโปรแกรมระบบย่อย GUI
แล้วปัญหาอาจเกิดจากอะไร?
คุณอาจจะพลาดไฟล์main
. และคุณอาจไม่มี (เหมาะสม) WinMain
เช่นกัน! จากนั้น g ++ หลังจากค้นหาmain
(ไม่เป็นเช่นนั้น) และสำหรับ Microsoft ที่ไม่ได้มาตรฐานWinMain
(ไม่เป็นเช่นนั้น) รายงานว่าส่วนหลังหายไป
การทดสอบด้วยแหล่งที่ว่าง:
C: \ test> พิมพ์ nul> y.cpp C: \ test> gnuc y.cpp -mwindows c: / ไฟล์โปรแกรม / mingw / bin /../ lib / gcc / mingw32 / 4.4.1 /../../../ libmingw32.a (main.o): main.c :(. text + 0xd2 ): การอ้างอิงที่ไม่ได้กำหนด ไปที่ `` WinMain @ 16 '' collect2: ld ส่งคืนสถานะการออก 1 ครั้ง C: \ test> _
main
หรือ a WinMain
หรือตรวจสอบให้แน่ใจว่าไฟล์ที่เกี่ยวข้องรวมอยู่ในโครงการ ไชโย
main
หรือwinmain
? ขอบคุณ
เพื่อสรุปโพสต์ข้างต้นโดย Cheers and hth - Alf ตรวจสอบให้แน่ใจว่าคุณมีmain()
หรือWinMain()
กำหนดไว้และ g ++ ควรทำในสิ่งที่ถูกต้อง
ปัญหาของฉันคือmain()
ถูกกำหนดไว้ภายในเนมสเปซโดยบังเอิญ
ฉันพบข้อผิดพลาดนี้ขณะคอมไพล์แอปพลิเคชันด้วย SDL สิ่งนี้เกิดจาก SDL กำหนดฟังก์ชันหลักของตัวเองใน SDL_main.h เพื่อป้องกันไม่ให้ SDL กำหนดฟังก์ชันหลักจำเป็นต้องกำหนดมาโคร SDL_MAIN_HANDLED ก่อนที่จะรวมส่วนหัว SDL.h
ลองบันทึกไฟล์. c ของคุณก่อนสร้าง ฉันเชื่อว่าคอมพิวเตอร์ของคุณอ้างอิงเส้นทางไปยังไฟล์ที่ไม่มีข้อมูลอยู่ภายใน
- มีปัญหาที่คล้ายกันเมื่อสร้างโครงการ C
ตรวจสอบว่าไฟล์ทั้งหมดรวมอยู่ในโครงการของคุณ:
ฉันมีข้อผิดพลาดเดียวกันนี้ปรากฏขึ้นหลังจากที่ฉันอัปเดต cLion หลังจากผ่านไปหลายชั่วโมงฉันสังเกตเห็นว่าไฟล์หนึ่งของฉันไม่ได้รวมอยู่ในเป้าหมายโครงการ หลังจากที่ฉันเพิ่มกลับเข้าไปในโปรเจ็กต์ที่ใช้งานอยู่ฉันหยุดรับข้อมูลอ้างอิงที่ไม่ได้กำหนดไปยัง winmain16 และรวบรวมโค้ดแล้ว
แก้ไข: ควรตรวจสอบการตั้งค่าการสร้างภายใน IDE ของคุณด้วย
(ไม่แน่ใจว่าข้อผิดพลาดนี้เกี่ยวข้องกับการอัปเดต IDE เมื่อเร็ว ๆ นี้ - อาจเป็นสาเหตุหรือสัมพันธ์กันเพียงแค่แสดงความคิดเห็นพร้อมข้อมูลเชิงลึกเกี่ยวกับปัจจัยนั้น ๆ !)
All you have to do is to tell Microsoft's linker which entry point to use, namely mainCRTStartup, which calls standard main
. มีวิธีทำEclipse CDT
ไหมเนื่องจากฉันไม่ได้ใช้บรรทัดคำสั่ง ขอบคุณ