c ++奇怪的c0000005错误

时间:2009-08-10 18:53:38

标签: c++ winapi

我正在开发一个可以在winlogon桌面上启动程序的项目。该程序在调试时工作正常,但是当我在ide之外启动它时,它会因臭名昭着的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,但它仍然崩溃了。我确定我犯了一些傻瓜错误而且我只是失明了。在此先感谢您的帮助!

3 个答案:

答案 0 :(得分:6)

我认为问题在于

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

一部分。该API使用 xyz ControlService 的最后一个参数来返回有关服务的状态信息。你实际上是在这里传递一个指向指针大小的内存区域的指针,这个指针太小而无法容纳 ControlService 想要填写的所有值。恕我直言你被咬了在运行时,因为执行 ControlService 调用将在 malloc 分配的指针空间之后直接覆盖随机内存。

尝试

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

代替。这里不需要动态分配结构。根据{{​​3}}, ControlService 仅用于返回状态信息;它不会存储在Windows内部数据结构中的某个位置。

有关结构内容的更多信息可以在documentation中。不知道,为什么它可能在调试期间工作。也许,与生产版本 malloc 相比,用于调试的 malloc 的行为略有不同?

答案 1 :(得分: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);

答案 2 :(得分: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

因此只有在出现故障时才会使用指针... :)