Archive for the ‘C++’ Category.

setsockopt设置组播返回10042(WSAENOPROTOOPT)错误

在编写组播程序时,需要加入组播组,调用setsockopt设置IP_ADD_MEMBERSHIP,代码如下:

/* join a multicast group */
if (multiaddr)
{ 
	struct ip_mreq mreq;
	mreq.imr_multiaddr.s_addr = inet_addr(multiaddr);
	mreq.imr_interface.s_addr = htonl(INADDR_ANY);
	if (setsockopt(socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char*)&mreq, sizeof(mreq)) < 0)
	{
		printf("setsockopt error, code;"<<WSAGetLastError());
	}
}

Continue reading ‘setsockopt设置组播返回10042(WSAENOPROTOOPT)错误’ »

解决vs2005编写程序报”应用程序配置不正确,程序无法启动”

使用vs2005编写完一个MFC程序后,在本机运行正常,发布到其它机器则会出现运行报错,提示“应用程序配置不正确,程序无法启动”,使用windows的事件查看器查看windows日志中的应用程序错误情况,发现提示

D:\test\bin_release\test.exe”的激活上下文生成失败。 
找不到从属程序集 Microsoft.VC80.MFC,processorArchitecture="x86",publicKeyToken="1fc8b3b9a1e18e3b",type="win32",version="8.0.50608.0"。 
请使用 sxstrace.exe 进行详细诊断。

这说明缺少Microsoft.VC80.MFC相关的库,找到C:\Program Files\Microsoft Visual Studio 8\VC\redist\x86\Microsoft.VC80.MFC目录,将该目录的动态库复制到运行程序所在目录,问题解决。

枚举进程调用Process32First失败返回24

在进行系统进程枚举时,调用了windows的API Process32First,结果调用失败,使用GetLastError返回错误号为24,这是因为没有初始化它的LPPROCESSENTRY32结构体dwSize值。

在MSDN对Process32First函数的介绍Remarks中提到,必须要为PROCESSENTRY32的dwSize赋值:

The calling application must set the dwSize member of PROCESSENTRY32 to the size, in bytes, of the structure. 

枚举进程代码如下:

int CMonitorModule::EnumProcess()
{
	HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	if (hProcessSnap == INVALID_HANDLE_VALUE)
	{
		DWORD error = GetLastError();
		printf("Cannot get system process snapshot (%d)\n", error);
		return -1;
	}

	PROCESSENTRY32 pe32 = {0};
	pe32.dwSize = sizeof(PROCESSENTRY32); //必须填充结构体的大小值
	if(!Process32First(hProcessSnap, &pe32))
	{
		DWORD error = GetLastError();
		printf("Process32First failed (%d)\n",error );
		CloseHandle(hProcessSnap);
		return -1;
	}
	do
	{
		printf(Process name :%s\n", pe32.szExeFile);
	} while(Process32Next(hProcessSnap, &pe32));

	CloseHandle( hProcessSnap );
	return 0;
}

双重检查锁定模式

双重检查锁定模式(也被称为”双重检查加锁优化”,”锁暗示”(Lock hint))是一种软件设计模式用来减少并发系统中竞争和同步的开销。双重检查锁定模式首先验证锁定条件(第一次检查),只有通过锁定条件验证才真正的进行加锁逻辑并再次验证条件(第二次检查)。

该模式在某些语言在某些硬件平台的实现可能是不安全的。有的时候,这一模式被看做是反模式。

它通常用于减少加锁开销,尤其是为多线程环境中的单例模式实现“惰性初始化”。惰性初始化的意思是直到第一次访问时才初始化它的值。

如果你想在多线程编程中安全使用单件模式(Singleton),最简单的做法是在访问时对其加锁,使用这种方式,假定两个线程同时调用Singleton::getInstance方法,其中之一负责创建单件:

Singleton* Singleton::getInstance() {
    Lock lock;      // scope-based lock, released automatically when the function returns
    if (m_instance == NULL) {
        m_instance = new Singleton;
    }
    return m_instance;
}

Continue reading ‘双重检查锁定模式’ »

程序猿老婆–C++获取网络时间

判断是否为文件夹

可以用FindFirstFile函数来获取提供的路径属性,以此来判断是否为文件夹。如下示例

bool IsDirectory(CString filePath)
{
	WIN32_FIND_DATA wfd;
	bool rValue = false;
	HANDLE hFind = FindFirstFile(filePath, &wfd);
	if ((hFind != INVALID_HANDLE_VALUE) && (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
	{
		rValue = true;
	}
	FindClose(hFind);
	return rValue;
}

同时,在windows中可以使用_stat()函数判断是否为文件夹
Continue reading ‘判断是否为文件夹’ »

获取exe可执行程序的命令行参数

在控制台中能够直接从参数中获取到命令行的参数,那么如果是应用程序,该如何从应用程序中获取命令行参数?

控制台可以使用下面的代码来获取命令行参数,参数下标从0开始,下标为0的参数是当前运行程序的路径,从下标1开始后面的参数是命令行中输入的参数

#include <stdio.h>
int main(int argc, char *argv[])
{
	int i;
	for (i = 0; i < argc; ++i)
	{
		printf("%d: %s\n", i, argv[i]);
	}
	return 0;
}

Continue reading ‘获取exe可执行程序的命令行参数’ »

MFC界面中英文自动切换

有时候程序需要运行在纯英文操作系统中,如果界面上有中文的话,会显示成乱码,那么就需要实现将界面切换成英文,修改MFC的资源文件就能够实现在英文操作系统中自动切换成英文界面。

MFC是能自动识别操作系统语言的,只需要添加相应语言的资源文件就可以了,比如我新建了一个Dialog工程,关于对话框是中文的,如下图

1
Continue reading ‘MFC界面中英文自动切换’ »

error C2146: 语法错误 : 缺少“;”(在标识符“PVOID64”的前面)

在使用VS2008编译工程的时候,发现编译出错,提示以下内容:

1>c:\program files\microsoft sdks\windows\v6.0a\include\winnt.h(236) : error C2146: 语法错误 : 缺少“;”(在标识符“PVOID64”的前面)
1>c:\program files\microsoft sdks\windows\v6.0a\include\winnt.h(236) : error C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int
1>c:\program files\microsoft sdks\windows\v6.0a\include\winnt.h(7818) : error C2146: 语法错误 : 缺少“;”(在标识符“Buffer”的前面)
1>c:\program files\microsoft sdks\windows\v6.0a\include\winnt.h(7818) : error C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int
1>c:\program files\microsoft sdks\windows\v6.0a\include\winnt.h(7818) : error C4430: 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int

在网上找了一些资料,说是因为有DirectX头文件引入顺序问题,要打开 工具->选项->项目和解决方案->VC++ 目录,确保条目 $(WindowsSdkDir)\include 和 $(FrameworkSDKDir)include 在任何DirectX目录的前面,但发现并没有DirectX目录,后来才找到原因,是由于在本地目录中加入DirectX的头文件,把本地目录中的BaseTsd.h删掉就行了。
Continue reading ‘error C2146: 语法错误 : 缺少“;”(在标识符“PVOID64”的前面)’ »

Windows下C++生成全局唯一GUID

有些时候,需要使用全局唯一的GUID,其实在windows环境中,windows的API提供了生成GUID的函数,即CoCreateGuid,需要引入头文件objbase.h

具体的生成代码如下:

#include <objbase.h>
#include <stdio.h>
 
//--生成GUID
const char* GenerateGUID()
{
    static char buf[64] = {0};
    GUID guid;
    if (S_OK == ::CoCreateGuid(&guid))
    {
        _snprintf(buf, sizeof(buf)
            , "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}"
            , guid.Data1
            , guid.Data2
            , guid.Data3
            , guid.Data4[0], guid.Data4[1]
        , guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5]
        , guid.Data4[6], guid.Data4[7]
        );
    }
    return (const char*)buf;
}
 
int main()
{
    //--COM
    CoInitialize(NULL);
 
    printf(GenerateGUID());
    printf("\r\n");
 
    //--COM
    CoUninitialize();
 
    return 0;
}

运行结果如下图:
1