快速溢出检测

#include <iostream>

// 可以检测 int * int, int + int 等等是否溢出。 不能检测unsigned int * unsigned int 是否溢出
// ( 因为一旦超过0x7FFFFFFF则会被置溢出位,但是对于unsigned int 显然还没有溢出)

// ---------------------- over flow test 1 ------------------------
#define  IF_NOT_OVERFLOW(X)	__asm jo overflow##x
#define  ELSEIF_OVERFLOW(X)	__asm jmp overflowend##x \
							__asm overflow##x:
#define	 END_NOT_OVERFLOW_TEST(X)	__asm overflowend##x:

// ---------------------- over flow test 2 ------------------------

#define  IF_OVERFLOW(X)	__asm jno not_overflow##x
#define  ELSEIF_NOT_OVERFLOW(X)	__asm jmp not_overflowend##x \
							__asm not_overflow##x:
#define	 END_OVERFLOW_TEST(X)	__asm not_overflowend##x:

int main(int, char*[])
{
	std::cout << "input x, y " << std::endl;
	int x;
	int y;
	std::cin >> x >> y;

	int m = x * y;

	IF_OVERFLOW( xym);
	std::cout << "over flow" << std::endl;
	ELSEIF_NOT_OVERFLOW(xym);
	std::cout << "m = " << m << std::endl;
	END_OVERFLOW_TEST(xym);

	return 0;
}

算法最新截图

效果截图

加入了多人处理,解决了一些bug。分割背景的算法重写了,地面的问题还在处理中,呵呵。

win7 x64系统下,32位程序可以使用3GB用户内存

如果在xp下,要是程序访问3GB用户内存,必须在boot.ini里打开/3GB选项。然而悲惨的是,不是所有机器在打开/3GB选项后,都能正常启动系统(具体原因未知,不过遇到过几台机都这样了)。
今天瞎碰,居然发现在64位的win7下,32位程序就可以直接使用到3GB用户内存(2011-05-27: 经测试,最高可以使用到4GB用户内存)。 当然,程序链接的时候,也同样需要打开Enable Large Address选项才能让该程序访问3GB的用户内存。

32位win7下则不行

ps,今天程序使用了2.8GB的虚拟地址, 其中物理内存2.1GB。再大一点就得大改程序了。好险!

Markless human motion capture

也算是我们team这一阶段的一个成果吧

Markless human motion capture

Get the Flash Player to see this player.

非官方非正式发布^_^

验证apache用户名与git提交的author是否匹配

使用git-http-backend来提供git服务,可以利用apache的用户认证模块来做读写控制。然而当用户提交的时候,git仓库里记录的却是用户本地设置的user.name (使用git config user.name设置,我们接下来称之为author), 而不是apache登陆时的用户名(committer)。 这显然不合逻辑。找了很久也没有找到在推送的时候,修改author为committer的方法,只好妥协一下了:在服务器端接收到push信息的时候,进行committer和author的检查,如果相同,则允许push。否则,拒绝该次push,并提示用户committer与author不同。
解决方案自然也就是这样的:在hooks目录下建立一个pre-receive文件, 当服务器接收push的时候,pre-receive将被自动调用。
另外,git-http-backend中已经建立了一个环境变量GIT_COMMITTER_USER,正好对应committer。因此只要检查GIT_COMMITTER_USER与每个提交的author是否匹配即可。

pre-receive内容如下:

#!/bin/sh

#获取提交信息
read COMMIT_FROM COMMIT_LAST COMMIT_REFS
if [ $COMMIT_FROM = "" ]
then
	echo "nothing committed?"
	echo 0
fi

REV_LIST=$(git rev-list $COMMIT_FROM..$COMMIT_LAST  $COMMIT_LAST --pretty=format:%an)

#echo rev-list: $COMMIT_FROM -- $COMMIT_LAST -- $REV_LIST
#分割REV_LIST,每3个字符串为一组提交,最后一个为该次提交author的名字

declare -i index=0
for AUTHOR_NAME in $REV_LIST; do
	((index++))
	if [ $index -eq 3 ]
	then
		((index=0))

		#检查提交的用户名(apache用户名),与提交作者,是否是同一个人
		if [ $GIT_COMMITTER_NAME = $AUTHOR_NAME ]
		then
			XXX=XXXX   #nothing todo
			#echo "committer name euqal author name, ok"
		else
			echo --rejected: committer:$GIT_COMMITTER_NAME doesnt match author:$AUTHOR_NAME
			exit 1
		fi
			#AUTHOR_NAME=AUTHOR_NAME+x;
	fi
done

echo "all is ok. done ^_^"
exit 0

^_^第一次写bash脚本,字符串分割还没学会,写了一个丑陋的for循环,呵呵。

继承基类operator=的问题

刚才群里难得讨论一次编程问题,大致是子类继承基类的operator=时,无法编译通过。代码如下:


template <class T>
class Base
{
protected:
	T *a;
public:
	Base<T>& operator=(T *p)
	{
		a = p;
		return *this;
	}
};

class Out
{
};

class Foo : public Base<Out>
{

};

int main(int argc, char* argv[])
{
	Foo foo;
	Out o;
	foo = &o;    // 这里编译失败
	return 0;
}

原因似乎是因为foo=&o这一项一定会在Foo里寻找 构造函数,或者operator=,但Foo恰恰都没有。解决方案? 修改Foo的实现为即可

class Foo : public Base<Out>
{
public:
	using Base<Out>::operator=;
};

当然最好的解决方案还是删除Foo类,使用typedef定义之,代码如下:

typedef Base<Out> Foo;
Foo foo;

亦即去掉继承,直接使用模板即可。

重载类的operator new实现new时内存对齐

在SSE里,要求数据是按16字节对齐的。直接使用_aligned_malloc,确实能保证对齐,只是在释放的时候,也必须配套使用_aligned_free。因此,我决定写一个基类,通过重载operator new和operator delete,自动调用_aligned_malloc和_aligned_free,一定程度上统一调用方式:使用的时候可以和普通类一样只是new/new[]和delete/delete[]即可实现自动对其的功能。

#pragma once

#include <malloc.h>
#include <new>
#include <cassert>

template< typename Base, size_t AlignmentSize>
class class_aligned_new
{
public:
    static void* operator new( size_t size )
	{
		if( size == 0) size = 1;
		void* raw = _aligned_malloc( size, AlignmentSize);
		if( raw == 0)			// 分配失败?
		{
			new_handler globalhandler = std::set_new_handler(0);
			std::set_new_handler(globalhandler); 

			if (globalhandler)		// 如果设置了new_handler,则调用它
			{
				(*globalhandler)();
			}
			else		// 否则抛出异常
			{
				throw std::bad_alloc();
			}
		}

		return raw;
	}

    static void* operator new[]( size_t size )
	{
		// 众多的检查,但是在release下,将会被优化掉
		int base_size = sizeof( Base);
		bool self_aligned = false;
		if ( base_size != 0)
		{
			self_aligned = ( base_size % AlignmentSize == 0);
		}

		if( self_aligned )
		{
			return operator new( size);
		}
		else
		{
			// 编译器计算的长度不能符合_aligned_malloc的要求,因此抛出异常
			throw std::bad_alloc();
		}
	}

    static void operator delete( void* addr )
	{
		if( addr != 0) _aligned_free( addr);
	}

	static void operator delete[]( void* addr)
	{
		operator delete( addr);
	}
};

使用起来和直接使用对象差不多,只是得注意new[]的时候的特殊要求。由于编译器会自动生成数组的长度,因此当Base的长度不能直接满足对其的要求时,禁止new[]

#include <iostream>
#include "aligned_class_new.h"

// 测试类,按16对齐
class test_class: public class_aligned_new< test_class, 16>
{
public:
	int a;
	int b;
	int c;
	int d;
};

int main( int argc, char* argv[])
{
	test_class* tc1 = new test_class;
	test_class* tc_array = new test_class[10];

	delete tc1;
	delete[] tc_array;
}

用起来是不是感觉和普通对象一样的呢? :)

宏与枚举

很简单的问题,所以还是先看代码吧:

#include <iostream>

enum SampleEnum
{
	Sample_Value_0 = 0,
	Sample_Value_1 = 1
};

#define SampleMacro	Sample_Value_1

int main( int argc, char* argv[])
{
	int sum = 0;
#if ( SampleMacro == Sample_Value_0)
	sum += 3;
#endif
#if (SampleMacro == Sample_Value_1)
	sum += 7;
#endif
	std::cout << sum << std::endl;
}

ok, 你会认为最终的输出的sum值是多少呢? 很遗憾,结果是10。

enum并不会在预处理阶段初始化,导致#if ( SampleMacro == Sample_Value_0) 和 #if ( SampleMacro == Sample_Value_1) 结果都成立,两段代码都被执行了。至于为何两端代码不是都不执行,这个我也说不出个所以然。

最终的解决方案是将 Sample_Value_0 和 Sample_Value_1 都写成宏定义。

另外补充一下,我的环境是vc2010

第 1 页,共 8 页12345678

Ringbinder theme by Themocracy