今天搭建android开发环境的时候,遇到一件郁闷的事,在创建模拟器的时候有snapshot选项,如果我选中的话(选中Enabled),就无法创建模拟器,会提示如下错误,[2013-01-08 22:59:45 - SDK Manager] Unable to find a 'E:\AndroidSofrware\android\\tools\lib\emulator\snapshots.img' file to copy into the AVD folder。但是如果我不选中的话,则可以正常创建模拟器并使用。而且即使我在该路径下添加snapshots.img文件之后依然会提示错误(在选中Enabled情况下),请问哪位大神能告诉我为什么,不胜感激。
还有一个错误,就是在启动模拟器的时候,出现
android 模拟器出错,emulator: ERROR: unknown virtual device name
解决办法:
遇到ERROR: unknown virtual device name这样的问题一般是由于创建的文件路径引用错误造成的。比如Vista可以设置用户文件到F盘下。这样在用Eclipse或者从命令行创建Android Emulator时,相应的文件是被放置到 “F:\Users\<username>\.android“ 下面了,而程序运行时仍然从 “C:\Users\<username>\.android“ 下查找相应的配置文件,从而导致上面的错误。
解决办法一:
把 “F:\Users\<username>\.android“ 下的文件复制到 “C:\Users\<username>\.android“ 下面即可解决这个问题,不过这样的解决方案有一个明显的缺点,那就是如果又新
建立AVD,又得重新复制。
解决办法二:
打开系统属性–>环境变量—>在“系统变量”那一个GroupBox下面选择“新建”–>变量名为 “ANDROID_SDK_HOME” (注意,这个变量名不能改变,只能是这个名字!),然后把变量值改为你想把AVD所在的”.android”文件夹放置的位置,比如:”F:\AndroidEmulator”,在这里我把它放在Android SDK包中,值为:”D:\SDK\Android\android-sdk-windows1.5_r3”
注:其实就是把ANDROID_SDK_HOME的值设置为“我的文档”的路径就OK,例如“D:\My Documents”
六、一些杂项
1、避免编写拷贝构造函数和赋值操作符,如果默认版本并不适用,可以考虑把拷贝构造函数和赋值操作符声明为私有,禁止类实例的复制
2、避免在析构函数中编写代码
需要析构函数的原因可能有好几个:
a、在基类中,可能需要声明虚拟析构函数,这样就可以使用一个指向基类的指针指向一个派生类的实例
b、在派生类中,并不需要把析构函数声明为虚拟函数,但是为了增加可读性,也可以这样做
c、可能需要声明析构函数并不抛出任何异常
下来讨论一下为什么析构函数应该是空的:
class Student
{
public:
Student
{
if (!number_)
{
number_ = new int(age);
}
}
~Student()
{
if (number_)
{
delete number_;
}
}
private:
int* number_;
};看看这个Student类,因为他在构造函数中获取了一些资源,所以需要在析构函数中释放掉。
但是现在问题来了,这个类的设计----每次添加一个表示个人描述的新元素(例如number_)时,都需要在析构函数中添加对应的清理代码,这就违背了“不要迫使程序员记住某些事情”的原则;另一个问题是,缺少安全检查,首先你的number_可能是要必须大于0的,这样还得在new的前面进行if判断,另外一个极端的情况:
#include "stdafx.h"
#include "iostream"
#include "string"
class A
{
public:
A() { std::cout << "Creating A" << std::endl; }
~A(){ std::cout << "Destroying A" << std::endl; }
};
class B
{
public:
B() { std::cout << "Creating B" << std::endl; }
~B(){ std::cout << "Destroying B" << std::endl; }
};
class C : public A
{
public:
C()
{
std::cout << "Creating C" << std::endl;
throw "Don't like C";
}
~C(){ std::cout << "Destroying C" << std::endl; }
private:
B b_;
};
int _tmain(int argc, _TCHAR* argv[])
{
try
{
C c;
}
catch (...)
{
std::cout << "Caught an exception" << std::endl;
}
return 0;
}因为在C中throw了一个异常,所以导致class C的析构函数没有被执行,这就导致了一些问题的产生
改成下面的形式设计就要好得多:
class Student
{
public:
Student(const int number, const char* name)
{
SCPP_ASSERT(number > 0, "number must be large 0");
number_ = new int(number);
SCPP_ASSERT(name != NULL, "name must be not null");
name_ = new std::string(name);
}
~Student()
{
}
private:
Student(const Student& student);
Student& operator = (const Student&);
scpp::ScopedPtr<int> number_;
scpp::ScopedPtr<std::string> name_;
};即使第二个安全检查抛出异常,执行name_的智能指针的析构函数仍然会被调用,并执行他的清理工作。另一个附带的好处是,我们并不需要操心把这些智能指针初始化为NULL,这是自动完成的。因此,可以看到构造函数抛出异常是一种潜在的危险行为;对应的析构函数将不会被调用,因此可能会存在问题,除非析构函数是空函数。
3、编写一致的比较操作符
常用的操作符有< > <= >= == !=,站在C++的角度,这些操作可以写成6个相互完全独立的函数,但是他们相互之间又有联系,比如x1>x2成立,x2<x1和x1>=x2也是成立的。所以,我们需要一些步骤来帮我实现这个目标(往之前的scpp_types.h上面添加):
#ifndef __SCCP_TYPES_H__
#define __SCCP_TYPES_H__
#include <ostream>
#include "scpp_assert.h"
template <typename T>
class TNumber
{
public:
TNumber(const T& x =0 )
:data_(x)
{
}
operator T() const
{
return data_;
}
TNumber &operator = (const T& x)
{
data_ = x;
return *this;
}
TNumber operator ++(int)
{
TNumber<T> copy(*this);
++data_;
return copy;
}
TNumber operator ++()
{
++data_;
return *this;
}
TNumber& operator += (T x)
{
data_ += x;
return *this;
}
TNumber& operator -= (T x)
{
data_ -= x;
return *this;
}
TNumber& operator *= (T x)
{
data_ *= x;
return *this;
}
TNumber& operator /= (T x)
{
SCPP_ASSERT(x != 0, "Attempt to divide by 0");
data_ /= x;
return *this;
}
T operator / (T x)
{
SCPP_ASSERT(x != 0, "Attempt to divide by 0");
return data_ / x;
}
private:
T data_;
};
typedef long long int64;
typedef unsigned long long unsigned64;
typedef TNumber<int> Int;
typedef TNumber<unsigned> Unsigned;
typedef TNumber<int64> Int64;
typedef TNumber<unsigned64> Unsigned64;
typedef TNumber<float> Float;
typedef TNumber<double> Double;
typedef TNumber<char> Char;
class Bool
{
public:
Bool(bool x = false)
:data_(x)
{
}
operator bool () const
{
return data_;
}
Bool& operator = (bool x)
{
data_ = x;
return *this;
}
Bool& operator &= (bool x)
{
data_ &= x;
return *this;
}
Bool& operator |= (bool x)
{
data_ |= x;
return *this;
}
private:
bool data_;
};
inline std::ostream& operator << (std::ostream& os, Bool b)
{
if (b)
{
os << "True";
}
else
{
os << "False";
}
return os;
}
#define SCPP_DEFINE_COMPARISON_OPERATORS(Class) \
bool operator < (const Class& that) const { return CompareTo(that) < 0; } \
bool operator > (const Class& that) const { return CompareTo(that) > 0; } \
bool operator ==(const Class& that) const { return CompareTo(that) ==0; } \
bool operator <=(const Class& that) const { return CompareTo(that) <=0; } \
bool operator >=(const Class& that) const { return CompareTo(that) >=0; } \
bool operator !=(const Class& that) const { return CompareTo(that) !=0; }
#endif
测试代码(vs2012+win7环境):
#include "stdafx.h"
#include "scpp_assert.h"
#include "iostream"
#include "scpp_vector.h"
#include "scpp_array.h"
#include "scpp_matrix.h"
#include "algorithm"
#include "scpp_types.h"
#include "scpp_refcountptr.h"
#include "scpp_scopedptr.h"
#include "scpp_ptr.h"
#include "string"
#define STUDENTAGE 10
class Student
{
public:
Student(int age)
{
SCPP_ASSERT(age > 0, "number must be large 0");
age_ = age;
}
int CompareTo(const Student& that) const
{
if (this->age_ > that.age_)
{
return 1;
}
else if(this->age_ == that.age_)
{
return 0;
}
else
{
return -1;
}
}
SCPP_DEFINE_COMPARISON_OPERATORS(Student);
private:
int age_;
};
int _tmain(int argc, _TCHAR* argv[])
{
Student studentFirst(STUDENTAGE);
Student studentSecond(STUDENTAGE);
if (studentFirst >= studentSecond)
{
std::cout << "(studentFirst > studentSecond) && (studentFirst == studentSecond)" << std::endl;
}
return 0;
}
4、使用标准C函数库的错误
C函数库中,在好几个方面都是不安全的,还可能导致程序崩溃
比如使用stdio.h
2.下载并安装libevent-2.0.21-stable.tar.gz: http://www.monkey.org/~provos/libevent/
3.下载并安装memcached-1.4.15.tar.gz:http://www.danga.com/memcached/download.bml
4.memcached 被安装在 /usr/local/bin/memcached
5.启动memcached,memcached p 11211 m 64m vv
6.可以通过telnet localhost 11211登录memcached,输入stats查看memcached状态