2009-08-10 173 views
0

我正在開發一個可以在winlogon桌面上啓動程序的項目。該程序在調試時可以正常工作,但是當我在ide之外啓動它時,它會因臭名昭着的c0000005錯誤而失敗。最奇怪的是,它似乎並沒有發生在任何特定的線上。下面是代碼:C++奇怪的c0000005錯誤

#include "stdafx.h" 
#include <windows.h> 
#include "BinRes.h" 
#include <string> 
#include <iostream> 

int main(int argc, char* argv[]) 
{ 
    if(argc != 2) 
    { 
     return 0; 
    } 

std::string a; 
a.append(BinRes::getAppLocation()); 
a.append("\\wls.exe"); 
BinRes::ExtractBinResource("EXE",102,"wls.exe"); 
Sleep(500); 
SC_HANDLE schsm; 
schsm = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS); 
SC_HANDLE schs; 
schs = CreateService(schsm,"WLS","WLS",SERVICE_ALL_ACCESS,SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS,SERVICE_DEMAND_START,NULL,a.c_str(),0,0,0,0,0); 
char* cd = argv[1]; 
LPCSTR* arg = (LPCSTR*)&cd; 
StartService(schs,1,arg); 
HANDLE endevent; 
endevent = OpenEvent(EVENT_ALL_ACCESS,TRUE,"ENDWLS"); 
WaitForSingleObject(endevent,INFINITE); 
SERVICE_STATUS ss; 
QueryServiceStatus(schs,&ss); 
if(ss.dwCurrentState != SERVICE_STOPPED) 
{ 
    LPSERVICE_STATUS xyz = (LPSERVICE_STATUS)malloc(sizeof(LPSERVICE_STATUS)); 
    ControlService(schs,SERVICE_CONTROL_STOP,xyz); 
} 
DeleteService(schs); 
//error occurs right here 
DeleteFile(a.c_str()); 
return 0; 
} 

錯誤總是DeleteService函數之後和下一行之前發生,但我敢肯定它是不是DeleteService函數,因爲該服務將被刪除。我試着註釋掉DeleteService和DeleteFile,但它仍然崩潰。我確信我犯了一些骷髏頭錯誤,只是失明而已。先謝謝您的幫助!

+2

對於什麼是值得的,是0000005訪問衝突。也許你應該插入一些返回值檢查並調用GetLastError()以查看在旅行期間是否發生了意外事件 – Fredrik 2009-08-10 18:59:08

+0

我同意Fredrik在調用API時始終檢查返回代碼 – LanceSc 2009-08-10 19:06:06

回答

6

我認爲問題出在

LPSERVICE_STATUS xyz = (LPSERVICE_STATUS)malloc(sizeof(LPSERVICE_STATUS)); 
ControlService(schs,SERVICE_CONTROL_STOP,xyz); 

部分內。最後一個參數xyzControlService被該API用於返回有關該服務的狀態信息。實際上,你實際上正在傳遞一個指向指針的指針這裏的內存區域,這個區域太小而不能容納所有的值,這些值需要填入其中.IMHO你在運行時被咬住,因爲執行ControlService調用將會在由malloc分配的指針空間後直接覆蓋隨機內存。

嘗試

SERVICE_STATUS xyz; 
memset(&xyz, 0, sizeof(xyz)); 
ControlService(schs, SERVICE_CONTROL_STOP, &xyz); 

代替。這裏不需要動態分配結構。根據documentationControlService將只用它來返回狀態信息;它不會被存儲在Windows內部數據結構的某處。

更多關於結構的內容可以在MS documentation。不知道,爲什麼它可能在調試過程中工作。也許,連接進行調試的malloc的行爲與生產版本malloc稍有不同?

+0

這看起來似乎是正確的,但仍然調用DeleteService – user37875 2009-08-10 19:24:02

+1

Yup 。沒有必要錯誤地覆蓋內存導致崩潰立即。可能是,下一次免費調用會發生崩潰(例如,可能會在調用c_str()或幾乎任何地方的過程中發生這種情況。您無法真正瞭解這類錯誤。 – Dirk 2009-08-10 19:33:22

4

在以LP開頭的windows API類型是指針,所以LPSERVICE_STATUS是指向SERVICE_STATUS的指針。因此sizeof(LPSERVICE_STATUS)返回一個指針的大小,SERVICE_STATUS的不是大小,這malloc不分配足夠的內存:

LPSERVICE_STATUS xyz = (LPSERVICE_STATUS)malloc(sizeof(LPSERVICE_STATUS)); 
ControlService(schs,SERVICE_CONTROL_STOP,xyz); 

正確的尺寸將是sizeof(SERVICE_STATUS)。同時你並不真的似乎需要動態分配內存的指針,指向一個局部變量應該工作以及:

SERVICE_STATUS xyz; 
ControlService(schs,SERVICE_CONTROL_STOP,&xyz); 
1

之所以通常不會失敗的最後一部分:

「只有當ControlService返回以下錯誤代碼之一時,服務控制管理器纔會填充結構:NO_ERROR,ERROR_INVALID_SERVICE_CONTROL,ERROR_SERVICE_CANNOT_ACCEPT_CTRL或ERROR_SERVICE_NOT_ACTIVE。否則,結構未填充。「

http://msdn.microsoft.com/en-us/library/ms682108%28VS.85%29.aspx

所以它永遠只能使用指針當事情失敗... :)