首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >创建窗口时ntdll.dll内部的SIGSEGV

创建窗口时ntdll.dll内部的SIGSEGV
EN

Stack Overflow用户
提问于 2014-04-23 08:49:40
回答 1查看 807关注 0票数 1

我正在尝试创建一个简单的GUI应用程序,在Windows7 x64上显示一个窗口。我使用FFI是为了从锈迹中调用Windows,但我一直在ntdll.dll中获得SIGSEGV。我做错了什么吗?

整个代码可以在sample上找到,但我会在这里发布主要内容。

  • winapi.h和winapi.c是Windows的C包装器。它们被编译成一个静态库(libwinapi)
  • winapi.rs是一个机箱,链接到libwinapi的FFI。
  • main.rs链接到winapi并显示一个窗口。

rustc -v的信息如下:

代码语言:javascript
复制
C:\Program Files (x86)\Rust\bin\rustc.exe 0.11-pre-nightly (7d725a3 2014-04-21 23:01:39 -0700)
host: i686-pc-mingw32

winapi.h

代码语言:javascript
复制
#ifndef WINAPI_H_
#define WINAPI_H_
#define UNICODE

#include <windows.h>
#include <stdbool.h>
#define API_CALL_CONVENTION __stdcall

#ifdef __cplusplus
extern "C" {
#endif


typedef struct {
    int width;
    int height;
    HWND handle;
} WindowContext;

bool API_CALL_CONVENTION createWindow(WindowContext* context, LPCTSTR title);
void API_CALL_CONVENTION mainLoop(WindowContext* context);

#ifdef __cplusplus
}
#endif

#endif // WINAPI_H_

winapi.c

代码语言:javascript
复制
#include "winapi.h"

bool API_CALL_CONVENTION createWindow(WindowContext* context, LPCTSTR title) {
    WNDCLASS wnd;
    memset(&wnd, 0, sizeof(wnd));
    HINSTANCE hInstance = GetModuleHandle(NULL);
    wnd.lpfnWndProc   = (WNDPROC)DefWindowProc;
    wnd.style         = CS_OWNDC;
    wnd.hInstance     = hInstance; 
    wnd.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wnd.hCursor = LoadCursor(NULL, IDC_ARROW);
    wnd.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); 
    wnd.lpszMenuName = NULL;
    wnd.lpszClassName = TEXT("opengles2.0");

    if (!RegisterClass (&wnd) ) {
        return false; 
    }

    DWORD wStyle = WS_VISIBLE | WS_POPUP | WS_BORDER | WS_SYSMENU | WS_CAPTION | WS_SIZEBOX;

    // Adjust the window rectangle so that the client area has
    // the correct number of pixels
    RECT windowRect;
    windowRect.left = 0;
    windowRect.top = 0;
    windowRect.right = context->width;
    windowRect.bottom = context->height;

    BOOL result = AdjustWindowRect(&windowRect, wStyle, FALSE);
    if (!result) {
        return false;
    }

    HWND handle = CreateWindow(
                        TEXT("opengles2.0"),
                        title,
                        wStyle,
                        0,
                        0,
                        windowRect.right - windowRect.left,
                        windowRect.bottom - windowRect.top,
                        NULL,
                        NULL,
                        hInstance,
                        NULL);

    // Set the ESContext* to the GWL_USERDATA so that it is available to the 
    // ESWindowProc
    SetWindowLongPtr(handle, GWLP_USERDATA, (LONG) (LONG_PTR) NULL);

    if(handle == NULL) {
      return false;
    }

    ShowWindow(handle, TRUE);
    context->handle = handle;
    return true;
}

void API_CALL_CONVENTION mainLoop(WindowContext* context) {
    MSG msg = { 0 };
    int done = 0;
    // DWORD lastTime = GetTickCount();

    while (!done) {
        int gotMsg = (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != 0);
        // DWORD curTime = GetTickCount();
        // float deltaTime = (float)( curTime - lastTime ) / 1000.0f;
        // lastTime = curTime;

        if ( gotMsg ) {
            if (msg.message==WM_QUIT) {
                done=1; 
            } else {
                TranslateMessage(&msg); 
                DispatchMessage(&msg); 
            }
        } else {
            SendMessage( context->handle, WM_PAINT, 0, 0 );
        }

        // Call update function if registered
        // if (esContext->updateFunc != NULL ) {
        //     esContext->updateFunc ( esContext, deltaTime );
        // }
    }
}

winapi.rs

代码语言:javascript
复制
#![crate_id = "winapi#0.1"]
#![crate_type = "lib"]
extern crate libc;
use libc::types::common::c95::{c_void};
use libc::types::os::arch::c95::{c_int};
use std::ptr::null;

// win32 related types
type LPCWSTR = *u16;
pub type HMODULE = *c_void;

pub struct WindowContext {
    pub width: c_int,
    pub height: c_int,
    pub handle: *c_void
}

#[cfg(windows)]
#[link(name="winapi")]
#[link(name="gdi32")]
extern "stdcall" {
    fn createWindow(context: *WindowContext, title: LPCWSTR) -> bool;
    fn mainLoop(context: *WindowContext);
}

// #[cfg(target_os = "win32", target_arch = "x86")]
#[cfg(windows)]
#[link(name="kernel32")]
extern "system" {
    fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;
}

pub fn get_module_handle(name: Option<~str>) -> HMODULE {
    match name {
        Some(n) => std::os::win32::as_utf16_p(n, |buf| unsafe { GetModuleHandleW(buf) }),
        None => unsafe { GetModuleHandleW(null())}
    }
}

pub fn create_window(context: *WindowContext, title: ~str) -> bool {
    std::os::win32::as_utf16_p(title, |buf| unsafe { createWindow(context, buf) })
}

pub fn main_loop(context: *WindowContext) {
    unsafe { mainLoop(context) }
}

main.rs

代码语言:javascript
复制
extern crate winapi;
use std::ptr::null;

fn main() {
    let handle = winapi::get_module_handle(None);
    println!("handle: {}", handle);
    let context = winapi::WindowContext {
        width: 320,
        height: 240,
        handle: null()
    };
    let result = winapi::create_window(&context, ~"Sample Window");
    if !result {
        println!("Failed to create window");
        return;
    }

    winapi::main_loop(&context);
}

构建日志

代码语言:javascript
复制
PS C:\Users\masato\Documents\GitHub\rust_sample> cmake -G "MinGW Makefiles"
-- The C compiler identification is GNU 4.8.1
-- The CXX compiler identification is GNU 4.8.1
-- Check for working C compiler: C:/Program Files (x86)/mingw-builds/x32-4.8.1-win32-dwarf-rev5/mingw32/bin/gcc.exe
-- Check for working C compiler: C:/Program Files (x86)/mingw-builds/x32-4.8.1-win32-dwarf-rev5/mingw32/bin/gcc.exe -- w
orks
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: C:/Program Files (x86)/mingw-builds/x32-4.8.1-win32-dwarf-rev5/mingw32/bin/g++.exe
-- Check for working CXX compiler: C:/Program Files (x86)/mingw-builds/x32-4.8.1-win32-dwarf-rev5/mingw32/bin/g++.exe --
 works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: C:/Users/masato/Documents/GitHub/rust_sample

PS C:\Users\masato\Documents\GitHub\rust_sample> mingw32-make.exe
Scanning dependencies of target winapi
[ 50%] Building C object CMakeFiles/winapi.dir/winapi/winapi.c.obj
Linking C static library libwinapi.a
[ 50%] Built target winapi
Scanning dependencies of target winapi_sample
[100%] Building C object CMakeFiles/winapi_sample.dir/winapi_sample.c.obj
C:\Users\masato\Documents\GitHub\rust_sample\winapi_sample.c: In function 'main':
C:\Users\masato\Documents\GitHub\rust_sample\winapi_sample.c:6:5: warning: format '%x' expects argument of type 'unsigne
d int', but argument 2 has type 'HMODULE' [-Wformat=]
     printf("Module addres: 0x%x\n", addr);
     ^
Linking C executable winapi_sample.exe
[100%] Built target winapi_sample

PS C:\Users\masato\Documents\GitHub\rust_sample> rustc winapi.rs

PS C:\Users\masato\Documents\GitHub\rust_sample> rustc .\main.rs -L .

gdb输出日志

代码语言:javascript
复制
PS C:\Users\masato\Documents\GitHub\rust_sample> gdb .\main.exe
GNU gdb (GDB) 7.6
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-w64-mingw32".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from C:\Users\masato\Documents\GitHub\rust_sample\main.exe...done.
(gdb) r
Starting program: C:\Users\masato\Documents\GitHub\rust_sample\main.exe
[New Thread 7060.0x1a0c]
[New Thread 7060.0x422c]
handle: 0x400000

Program received signal SIGSEGV, Segmentation fault.
0x76f3fc62 in ntdll!ZwMapViewOfSection () from C:\Windows\system32\ntdll.dll
(gdb) bt
#0  0x76f3fc62 in ntdll!ZwMapViewOfSection () from C:\Windows\system32\ntdll.dll
#1  0x76f3fc62 in ntdll!ZwMapViewOfSection () from C:\Windows\system32\ntdll.dll
#2  0x762ceba2 in MapViewOfFile () from C:\Windows\syswow64\KernelBase.dll
#3  0x70a25313 in UxTheme!GetThemeBitmap () from C:\Windows\SysWOW64\uxtheme.dll
#4  0x70a251e5 in UxTheme!GetThemeBitmap () from C:\Windows\SysWOW64\uxtheme.dll
#5  0x70a253e5 in UxTheme!GetThemeBitmap () from C:\Windows\SysWOW64\uxtheme.dll
#6  0x70a25a77 in UxTheme!GetThemeBitmap () from C:\Windows\SysWOW64\uxtheme.dll
#7  0x70a25cc4 in UxTheme!GetThemeBitmap () from C:\Windows\SysWOW64\uxtheme.dll
#8  0x70a22094 in UxTheme!CloseThemeData () from C:\Windows\SysWOW64\uxtheme.dll
#9  0x70a24260 in UxTheme!IsThemePartDefined () from C:\Windows\SysWOW64\uxtheme.dll
#10 0x70a2421d in UxTheme!IsThemePartDefined () from C:\Windows\SysWOW64\uxtheme.dll
#11 0x70a246ed in UxTheme!ThemeInitApiHook () from C:\Windows\SysWOW64\uxtheme.dll
#12 0x74daacd4 in UnregisterClassW () from C:\Windows\syswow64\user32.dll
#13 0x74daab0e in UnregisterClassW () from C:\Windows\syswow64\user32.dll
#14 0x76f3010a in ntdll!KiUserCallbackDispatcher () from C:\Windows\system32\ntdll.dll
#15 0x0028fa9c in ?? ()
#16 0x74dbc6f1 in USER32!AdjustWindowRect () from C:\Windows\syswow64\user32.dll
#17 0x004cc196 in createWindow@8 (context=0x28fcc8, title=0x9f3618 L"Sample Window")
    at C:\Users\masato\Documents\GitHub\rust_sample\winapi\winapi.c:85
#18 0x00403bfd in create_window::closure.1804 ()
#19 0x00403b8a in os::win32::as_utf16_p::h611005080090069878::v0.1 ()
#20 0x00403a2e in create_window::h0d38b3844b04f5aaEba::v0.1 ()
#21 0x0040174c in main::h8f0d1dbc5859ab98gaa::v0.0 ()
#22 0x0042cac8 in start::closure.7798 ()
#23 0x004c035c in rt::task::Task::run::closure.40266 ()
#24 0x004c46b5 in rt::unwind::Unwinder::try::try_fn::hf6246262045efccdJS9::v0.11.pre ()
#25 0x004cc006 in rust_try ()
#26 0x004c0234 in rt::task::Task::run::h08ef5174e2ea21abwj8::v0.11.pre ()
#27 0x0042c97d in start::h07163dfeb7ec96475Ld::v0.11.pre ()
#28 0x0042c829 in lang_start::h59c5ddaef2ad2b17pLd::v0.11.pre ()
#29 0x00401810 in main ()
(gdb)
EN

回答 1

Stack Overflow用户

发布于 2014-04-23 09:19:05

我可以在您的代码中看到以下问题:

  • 在检查SetWindowLongPtr是否成功之前,先调用CreateWindow
  • 您应该将windowRect.leftwindowRect.top传递给CreateWindow以获得xy坐标。
  • 您的消息循环有点奇怪。经典的GetMessage循环有什么问题?
  • 发送WM_PAINT消息的代码是错误的。你不能那样做。如果您想重新绘制,请使用InvalidateRect

我怀疑上述任何一项都不能解释你的错误。但是,我当然想整理一下消息循环。它应该是这样的:

代码语言:javascript
复制
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}

如果我使用您的Win32 C代码并使用我的C编译器编译它,那么它就运行得很好。这使我认为问题在于你正在使用的链接过程。AdjustWindowRect中的访问冲突似乎很奇怪。堆栈跟踪有许多来自主题API的函数。你的计划是如何实现的?

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23239272

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档