tham chiếu không xác định đến `WinMain @ 16 '


110

Khi tôi cố gắng xây dựng một chương trình bằng cách sử dụng Eclipse CDT, tôi nhận được những điều sau:

/mingw/lib/libmingw32.a(main.o):main.c:(.text+0x106): tham chiếu không xác định đến `WinMain @ 16

Tại sao vậy? Và, làm thế nào tôi có thể giải quyết vấn đề này?

Câu trả lời:


183

Hãy xem xét chương trình cấp API của Windows sau:

#define NOMINMAX
#include <windows.h>

int main()
{
    MessageBox( 0, "Blah blah...", "My Windows app!", MB_SETFOREGROUND );
}

Bây giờ chúng ta hãy xây dựng nó bằng cách sử dụng chuỗi công cụ GNU (tức là g ++), không có tùy chọn đặc biệt. Đâygnuc chỉ là một tệp hàng loạt mà tôi sử dụng cho việc đó. Nó chỉ cung cấp các tùy chọn để làm cho g ++ trở nên chuẩn hơn:

C: \ test> gnuc x.cpp

C: \ test> objdump -x a.exe | findstr / i "^ hệ thống con"
Hệ thống con 00000003 (Windows CUI)

C: \ test> _

Điều này có nghĩa là trình liên kết theo mặc định đã tạo ra một hệ thống con bảng điều khiển có thể thực thi được. Các hệ thống phụ giá trị trong phần đầu tập tin để nói cho Windows những dịch vụ chương trình yêu cầu. Trong trường hợp này, với hệ thống giao diện điều khiển, chương trình yêu cầu một cửa sổ giao diện điều khiển.

Điều này cũng làm cho trình thông dịch lệnh đợi chương trình hoàn thành.

Bây giờ hãy xây dựng nó với hệ thống con GUI , điều này có nghĩa là chương trình không yêu cầu cửa sổ giao diện điều khiển:

C: \ test> gnuc x.cpp -mwindows

C: \ test> objdump -x a.exe | findstr / i "^ hệ thống con"
Hệ thống con 00000002 (Windows GUI)

C: \ test> _

Hy vọng rằng điều đó là ổn cho đến nay, mặc dù -mwindowslá cờ chỉ là tài liệu bán phần.

Việc xây dựng mà không có cờ bán tài liệu đó, người ta sẽ phải nói cụ thể hơn cho trình liên kết biết giá trị hệ thống con nào mà người ta mong muốn và một số thư viện nhập API Windows nói chung sẽ phải được chỉ định rõ ràng:

C: \ test> gnuc x.cpp -Wl,-subsystem, windows

C: \ test> objdump -x a.exe | findstr / i "^ hệ thống con"
Hệ thống con 00000002 (Windows GUI)

C: \ test> _

Điều đó hoạt động tốt, với chuỗi công cụ GNU.

Nhưng còn chuỗi công cụ Microsoft, tức là Visual C ++ thì sao?

Vâng, xây dựng như một hệ thống con bảng điều khiển có thể thực thi hoạt động tốt:

C: \ test> msvc x.cpp user32.lib
x.cpp

C: \ test> dumpbin / headers x.exe | tìm / i "hệ thống con" | tìm / i "Windows"
               3 hệ thống con (Windows CUI)

C: \ test> _

Tuy nhiên, với việc xây dựng chuỗi công cụ của Microsoft dưới dạng hệ thống con GUI không hoạt động theo mặc định:

C: \ test> msvc x.cpp user32.lib / link / subsystem: windows
x.cpp
LIBCMT.lib (wincrt0.obj): lỗi LNK2019: ký hiệu bên ngoài chưa được giải quyết _WinMain @ 16 được tham chiếu trong hàm ___tmainCRTStartu
p
x.exe: lỗi nghiêm trọng LNK1120: 1 bên ngoài chưa được giải quyết

C: \ test> _

Về mặt kỹ thuật, điều này là do trình liên kết của Microsoft không phải là tiêu chuẩn theo mặc định cho hệ thống con GUI . Theo mặc định, khi hệ thống con là GUI, thì trình liên kết của Microsoft sử dụng điểm nhập thư viện thời gian chạy , hàm nơi bắt đầu thực thi mã máy, được gọi winMainCRTStartup, gọi là không chuẩn của Microsoft WinMainthay vì chuẩn main.

Không có vấn đề lớn để sửa chữa điều đó, mặc dù.

Tất cả những gì bạn phải làm là cho trình liên kết của Microsoft biết điểm nhập nào sẽ sử dụng, cụ thể là điểm mainCRTStartupnào gọi là tiêu chuẩn main:

C: \ test> msvc x.cpp user32.lib / link / subsystem: windows / entry: mainCRTStartup
x.cpp

C: \ test> dumpbin / headers x.exe | tìm / i "hệ thống con" | tìm / i "Windows"
               2 hệ thống con (Windows GUI)

C: \ test> _

Không sao, nhưng rất tẻ nhạt. Và phức tạp và ẩn giấu đến nỗi hầu hết các lập trình viên Windows, những người chủ yếu chỉ sử dụng các công cụ không phải là tiêu chuẩn theo mặc định của Microsoft, thậm chí không biết về nó, và nhầm tưởng rằng một chương trình hệ thống con Windows GUI “phải” có tiêu chuẩn WinMainthay vì tiêu chuẩn. main. Nói cách khác, với C ++ 0x, Microsoft sẽ gặp vấn đề với điều này, vì trình biên dịch sau đó phải quảng cáo xem nó đang ở chế độ chờ hay được lưu trữ (khi được lưu trữ, nó phải hỗ trợ tiêu chuẩn main).

Dù sao, đó là lý do tại sao g ++ có thể phàn nàn về việc WinMainthiếu: đó là một chức năng khởi động không chuẩn ngớ ngẩn mà các công cụ của Microsoft yêu cầu theo mặc định cho các chương trình hệ thống con GUI.

Nhưng như bạn có thể thấy ở trên, g ++ không có vấn đề gì với tiêu chuẩn mainngay cả đối với một chương trình hệ thống con GUI.

Vì vậy, những gì có thể là vấn đề?

Chà, có lẽ bạn đang thiếu a main. Và bạn có thể không có (thích hợp) WinMain! Và sau đó g ++, sau khi đã tìm kiếm main(không phải như vậy) và cho không phải tiêu chuẩn của Microsoft WinMain(không có như vậy), báo cáo rằng cái sau bị thiếu.

Thử nghiệm với một nguồn trống:

C: \ test> gõ nul> y.cpp

C: \ test> gnuc y.cpp -mwindows
c: / program files / mingw / bin /../ lib / gcc / mingw32 / 4.4.1 /../../../ libmingw32.a (main.o): main.c :(. text + 0xd2 ): tham chiếu không xác định
ce thành `WinMain @ 16 '
Collect2: ld trả về 1 trạng thái thoát

C: \ test> _

3
@Alf P. Steinbach. Cảm ơn rất nhiều cho câu trả lời tốt đẹp của bạn. Đối với All you have to do is to tell Microsoft's linker which entry point to use, namely mainCRTStartup, which calls standard main. Có cách nào để làm điều đó Eclipse CDTvì tôi không sử dụng dòng lệnh. Cảm ơn
Đơn giản

1
@ user588855: vì bạn đang sử dụng g ++ nên (có thể) không áp dụng cho bạn. Chỉ phần ở cuối (có thể) được áp dụng. Đó là, xác định a mainhoặc a WinMain, hoặc đảm bảo rằng tệp liên quan được đưa vào dự án. Cheers,
Cheers and hth. - Alf

@Alf P. Steinbach. Ý bạn là gì khi xác định mainhoặc winmain? Cảm ơn
Đơn giản

1
Tôi vừa tạo một tệp có tên main.cpp có mã: int main () {}
Thật vậy,

3
Tôi sẽ rất vui nếu mỗi người có thể giải thích cho người dưới quyền. Có thể những độc giả khác cũng có quan niệm sai lầm tương tự (bất kể nó là gì), và sau đó chúng tôi có thể làm rõ điều đó. Mọi người sẽ được hưởng lợi, thay vì một số bị lừa. Vì vậy, vui lòng giải thích downvote của bạn. Cảm ơn bạn.
Chúc mừng và hth. - Alf

68

Tổng hợp bài viết trên của Cheers và hth. - Alf, Hãy chắc chắn rằng bạn có main()hoặc đã WinMain()định nghĩa và g ++ sẽ làm đúng.

Vấn đề của tôi là main()tình cờ được xác định bên trong một không gian tên.


Chỉ cần nhận ra một cái gì đó quan trọng về tất cả những điều này. Trong trường hợp của tôi, nó không tìm thấy hàm main () vì tôi không khai báo bất kỳ đối số nào (argc, argv). Sau khi thêm vào, nó tìm thấy chính. Ngoài ra, bản chất của cách hoạt động này có nghĩa là mingw đang cố gắng trợ giúp bằng cách cung cấp chính của chính nó mà đến lượt nó lại gọi WinMain. Các chương trình GUI sẽ chỉ có WinMain và sơ khai chính trong mingw được sử dụng để đạt được điều đó. Nếu bạn có một main, thì nó sẽ sử dụng nó để thay thế.
Jeff Muir

extern "C" int main (void) đã khắc phục sự cố cho tôi
dryler

33

Tôi đã gặp phải lỗi này khi biên dịch ứng dụng của mình với SDL. Điều này là do SDL xác định chức năng chính của chính nó trong SDL_main.h. Để ngăn SDL xác định chức năng chính, một macro SDL_MAIN_HANDLED phải được xác định trước khi tiêu đề SDL.h được bao gồm.


Câu trả lời chính xác! +1
Mohammad Kanan

Cảm ơn rất nhiều! Lệnh này hoạt động: gcc main.c -I "E: \ Libs \ SDL2-devel-2.0.12-mingw \ SDL2-2.0.12 \ i686-w64-mingw32 \ include" -I "E: \ Libs \ SDL2_ttf- devel-2.0.15-mingw \ SDL2_ttf-2.0.15 \ i686-w64-mingw32 \ include "-L" E: \ Libs \ SDL2-devel-2.0.12-mingw \ SDL2-2.0.12 \ i686-w64- mingw32 \ lib "-L" E: \ Libs \ SDL2_ttf-devel-2.0.15-mingw \ SDL2_ttf-2.0.15 \ i686-w64-mingw32 \ lib "-lSDL2 -lSDL2main -lSDL2_ttf -o app.exe
8Observer8

5

Hãy thử lưu tệp .c của bạn trước khi xây dựng. Tôi tin rằng máy tính của bạn đang tham chiếu đến đường dẫn đến một tệp không có thông tin bên trong nó.

- Gặp vấn đề tương tự khi xây dựng các dự án C


Điều này thực sự đã giải quyết được vấn đề của tôi và tôi để lại nhận xét này để giúp nó được chú ý nhiều hơn.
David Chen,

0

Kiểm tra xem tất cả các tệp có được bao gồm trong dự án của bạn không:

Tôi đã có cùng một lỗi này bật lên sau khi tôi cập nhật cLion. Sau nhiều giờ mày mò, tôi nhận thấy một trong những tệp của tôi không được đưa vào mục tiêu dự án. Sau khi tôi thêm lại nó vào dự án đang hoạt động, tôi đã ngừng nhận tham chiếu không xác định cho winmain16 và mã được biên dịch.

Chỉnh sửa: Bạn cũng nên kiểm tra cài đặt xây dựng trong IDE của mình.

(Không chắc liệu lỗi này có liên quan đến việc cập nhật IDE gần đây hay không - có thể là quan hệ nhân quả hoặc đơn giản là tương quan. Vui lòng bình luận với bất kỳ thông tin chi tiết nào về yếu tố đó!)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.