• About
    • Resume
A Game Developer also plays some guitar

Tag Archives: 崩溃

iOS开发与OpenGL ES相关问题整理(1)

May 22, 2011 2:21 pm / 1 Comment / Benny Chen

在极其有限的工作日的晚上和周末进行着iOS上game programming的研究,进展非常缓慢,不过还是有必要将过程中的一些问题随时记录下来。

  • OpenGL ES崩溃在函数’glMatrixMode’

    这很有可能是因为在OpenGL ES2的context中使用OpenGL ES1的函数,ES1是固定函数渲染管线 (fixed function pipeline),而ES2是可编程的渲染管线 (programmable pipeline),ES2不再支持这些ES1的固定渲染管线的函数, 比如’glMatrixMode’。所以当ES2遇到这些不支持的ES1函数时,你的程序会收到一个’EXC_BAD_ACCESS’消息并且崩溃。通过gdb查看callstack,显示最后一个函数是gliUnimplemented:

    #0  0x0b05c0e5 in gliUnimplemented ()
    #1  0x00a1c6c3 in glMatrixMode ()
    

    如果一定要使用ES1函数, 你只能以ES1来初始化你的GL context:

    EAGLContext *aContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
    
  • 函数’pathForResource’返回nil

    需要将资源文件添加到项目的’Groups & Files’中

  • OpenGL ES崩溃在绘制函数’glDrawArrays’

    这可能是因为你启动了GL的某个渲染状态(比如vertex,color,texture coordinate等等,这里有所有可能状态的清单),但是却没有在绘制函数(比如’glDrawArray’)进行之前,设置该状态所对应的数据指针。

    比如说:

    glEnableClientState( GL_COLOR_ARRAY );
    glColorPointer( 4, GL_UNSIGNED_BYTE, 0, youColorArray );
    

    对于上面这两句代码,如果你设置了使用color数组,但是却没有设置color数组指针,在真正的绘制时你的程序就会因为找不到对应的指针而崩溃。同样的, 如果你调用了‘glEnableClientState(GL_TEXTURE_COORD_ARRAY), 则你也需要通过glTexCoordPointer()设置纹理坐标的数组指针,如此类推。

  • 怎么样通过OpenGL ES以像素为单位来绘制,而不是屏幕比例?

    在iPhone上通过OpenGL ES进行2D绘制时,默认的原点位置在屏幕中央,并且屏幕的坐标范围依次是从-1到1,不管是横轴还是纵轴。如下图所示,GL中的默认的单位1分别代表着屏幕长度和宽度的一半。

    图片来自book: ‘Learning iOS Game Programming_A Hands-On Guide to Building Your First iPhone Game’
    如果希望将原点移动到屏幕左下角,并且绘制时希望以像素为单位,只需要通过glOrthof函数将投影矩阵设置成一个垂直投影矩阵即可,代码如下:

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrthof( 0, framebufferWidth, 0, framebufferHeight, -1, 1 );
    
  • Posted in: Game Programming, iOS / Tagged: glDrawArray, glMatrixMode, ios, opengles, pathForResource, 像素, 崩溃

    Static Initialization Order Fiasco

    August 19, 2010 12:59 pm / Leave a Comment / Benny Chen

    Static Initialization Order Fiasco (SIOF),我也是最近才知道了这个说法,因为在开发程序的时候被它bug了:对于一个static变量,不管它是全局的或者是类的成员变量,访问它的时候不一定总是成功的,甚至会造成程序crash,因为不能保证它在被访问时已经被初始化了(跟初始化的顺序有关,所以称为初始化顺序的Fiasco)。以下将制造一个非常简单的SIOF情形:

    Whatever.h

    #include <vector>
    #include <string>
    class Whatever
    {
    public:
    	Whatever()
    	{
    		cout << "Construct Whatever" << endl;
    		Display();
    	}
    	~Whatever()
    	{
    		cout << "Destruct Whatever" << endl;
    		Display();
    	}
    	void Display()
    	{
    		cout << "static int:" << i << endl;
    		cout << "static string:" << m_str << endl;
    		cout << "static vector:" << m_vec.front() << endl;
    	}
    
    private:
    	static int i;
    	static std::string m_str;
    	static std::vector<char> m_vec;
    };
    

    Whatever.cpp

    #include "Whatever.h"
    
    int Whatever::i = 500;
    string Whatever::m_str = "something";
    vector<char> Whatever::m_vec = vector<char>( 10, 'a' );
    

    一个简单的类,Whatever,包含几个static成员变量,然后在构造函数和析构函数中都分别打印这些静态变量的值,乍一看似乎没什么问题,但却有潜在的SIOF的风险。我们容易默认为在调用Whatever的构造函数的时候,Whatever空间中的static的成员变量已经被初始化了,其实不然,现在制造一个SIOF引起crash的情形:

    #include "Whatever.h"
    Whatever g_whatever; 
    int main()
    {
    	...
    }
    

    因为g_whatever是global变量,所以最先被初始化,在调用Whatever的构造函数的时候,Whatever空间的静态成员变量还未被初始化,所以访问这些静态变量肯定出错。在VS的编译器下测试的结果:

    Construct Whatever
    static int:5
    static string:
    (调用m_vec.front()导致程序crash)

    奇怪的是对于int这种built-in的类型却能得到正确的值,不知编译器在背后都做了哪些手脚,猜想可能是在程序编译的时候他们就被值替换了。而string和vector应该都属于自定义类型(初始化需要调用构造函数),未初始化之前访问肯定是错误的,所以打印出的string是个空值,而访问一个空的vector的front元素则直接造成程序crash。

    根据初始化和释放的对称关系,所以在析构函数中访问这些静态变量同样也是失败的,因为在析构g_whatever的时候,Whatever空间的静态变量已经被解决掉了。

    SIOF是非常难于检测的问题,这个例子是一种最简单的情形,在我的项目中,我并没有定义什么global的成员,但是因为使用了很多前置声明(forward declaration),还有一些Singleton,造成了一个非常隐蔽的SIOF,花了很大的力气才找到,痛苦的过程。

    要解决SIOF问题,需要用一个function来包装static变量,即利用函数内static变量的construct-on-first-use特性。

    修改后的Whatever.h

    class Whatever
    {
    public:
    	Whatever()
    	{
    		cout << "Construct Whatever" << endl;
    		Display();
    	}
    	~Whatever()
    	{
    		cout << "Destruct Whatever" << endl;
    		Display();
    	}
    	void Display()
    	{
    		cout << "static vector:" << GetStaticVector().front() << endl;
    	}
    
    private:
    	vector<char>& GetStaticVector()
    	{
    		static vector<char> vec = vector<char>( 10, 'a' );
    		return vec;
    	}
    };
    

    用GetStaticVector来包装之前所需要的静态的vector,就能保证在调用的时候,它一定已经被初始化了。再次运行之前的测试程序,OK了。

    总之,我们对于static变量的使用要保持一颗警惕的心,如果不确定在使用时它是否已经被初始化,就要使用函数包装static变量来防止Static Initialization Order FIASCO!
    Fiasco, what a cool word.

    Posted in: C++ / Tagged: crash, static initialization order fiasco, 初始化, 崩溃, 静态变量, 顺序

    LinkedIn

    Milan Petrovic

    Categories

    • In My Life (25)
      • A Day in the Life (8)
      • English Learning (2)
      • Learn a Word (7)
      • Something In The Way (8)
    • Music Heaven (8)
      • Guitar (1)
      • In Concert (1)
      • Lyrics (3)
    • OK Computer (54)
      • 3D (3)
      • C++ (10)
      • Computer Graphics (15)
      • Game Programming (23)
      • iOS (6)
      • Linux (1)
      • Lua (9)
      • My Projects (3)
      • Some Experiences (9)
      • Talking in Code (2)
      • Unity (2)
    • Quotations (2)
    • Uncategorized (1)
    • Visca Barça (24)
      • FCB BJ (5)

    Recent Posts

    • [译]优化你的手机游戏(没有延迟的,才是健康的)- 一篇给游戏美术设计师读的文章
    • 新浪微博API for MOAI
    • 稍后继续
    • Unity Developer ++
    • Another Thread @ Moai Forum
    • 1st Day of Golden Week
    • 为SyntaxHighlighter添加新语言
    • 基于Lua的State Pattern
    • Class Diagram of Pacman
    • 基于Moai的Pacman

    Recent Comments

    • 约修亚_RK on 为SyntaxHighlighter添加新语言
    • 爱装的小男孩 on 小心DLL链接静态库时的内存错误
    • happyfire on Game Loop的几种实现方式
    • William on 新浪微博API for MOAI
    • Benny Chen on 新浪微博API for MOAI
    • your man on 新浪微博API for MOAI
    • 你家男人 on 稍后继续
    • 逍遥 on 关于对std::vector的遍历
    • papa on Unity Developer ++
    • T客网 ︱ Techpot » Blog Archive » iOS开发与OpenGL ES相关问题整理(1) on iOS开发与OpenGL ES相关问题整理(1)

    Tags

    2d 3D 3dsmax 3ds max air Apply architecture Asia tour barca Beijing bilbao binary search blocked bob boost bruce springsteen C++ capo CGContextDrawImage Champions League Change DLL DX10 eval exporter flash framework frustum culling game game engine iniesta ios linux lua Moai opengles pacman plug-in plugin 北京 导出插件 崩溃 巴萨 游戏引擎 踢球
    © Copyright 2026 - A Game Developer
    Infinity Theme by DesignCoral / WordPress