编译器优化陷阱——全局指针多次使用异常

做程序开发一定会和编译器打交道,编译器优化可以给我们代码运行带来一定的提升,但也可能存在一些意想不到的问题。下面就是我在开发时候遇到的一个坑,希望可以给大家一些借鉴

直接上代码说话吧

 1 static unsigned char* s_data = NULL;                    //存储一帧视频数据
 2 void DoRendering ()
 3 {
 4     // D3D11 case
 5     if (s_DeviceType == kUnityGfxRendererD3D11 && EnsureD3D11ResourcesAreCreated())
 6     {
 7         ID3D11DeviceContext* ctx = NULL;
 8         g_D3D11Device->GetImmediateContext (&ctx);
 9
10         // update native texture from code
11         if (g_TexturePointer)
12         {
13             ID3D11Texture2D* d3dtex = (ID3D11Texture2D*)g_TexturePointer;
14             D3D11_TEXTURE2D_DESC desc;    //保存纹理信息
15             d3dtex->GetDesc (&desc);    //获取纹理信息
16
17             //unsigned char* s_data = new unsigned char[desc.Width*desc.Height*4];
18             //char* errorMessage = new char[80];
19             char errorMessage[80];
20
21             if (!s_isInitRender)
22             {
23                 s_data = (unsigned char*)malloc(desc.Width*desc.Height*4);
24                 InitRender(desc.Width, desc.Height, 2, errorMessage);    //初始化渲染参数
25                 if (NULL == s_hThread)
26                 {
27                     unsigned threadID;    //线程ID
28                     s_hThread = (HANDLE)_beginthreadex( NULL, 0, SfpRefreshThread, NULL, 0, &threadID );     //新线程控制渲染频率
29                 }
30             }
31             //控制刷新频率
32             if ( s_refreshFlag && s_isInitRender )
33             {
34                 if ( !RenderTextureWithVideo(desc.Width*4,s_data))
35                 {
36                     ReleaseRender(2);           //释放渲染内存
37                     free(s_data);
38                     s_data = NULL;
39                 }
40                 ctx->UpdateSubresource (d3dtex, 0, NULL, s_data, desc.Width*4, 0);
41                 s_refreshFlag = false;
42             }
43         }
44         ctx->Release();
45     }

在第1行定义了一个全局指针变量,在函数DoRendering中分配和释放内存,多次调用这个函数,就会多次分配和释放该指针的内存。

但是在VC编译器中,第二次调用该函数后会报错,但在GCC编译器中就不会。

所以,如果遇到以上情况,换个编译器试试!

时间: 2024-07-30 00:07:48

编译器优化陷阱——全局指针多次使用异常的相关文章

[Inside HotSpot] C1编译器优化:全局值编号(GVN)

1. 值编号 我们知道C1内部使用的是一种图结构的HIR,它由基本块构成一个图,然后每个基本块里面是SSA形式的指令,关于这点如可以参考[Inside HotSpot] C1编译器工作流程及中间表示.值编号(Value numbering)是指为每个计算得到的值分配一个独一无二的编号,然后遍历指令寻找可优化的机会.比如下面的代码: a = 1;b=4; c = a+b; d = a+b; e = b; 编译器可以在计算a的时候为它指定一个hash值(0x12a3e)然后放入hash表:b同理指定

C语言 之编译器优化

C语言的编译器会对变量和代码进行一定的优化,我们看下面这个例子. int a,b,c; a=1; b=a; c=b; 这个程序正常运行的时候会这样子:先把a指向的内存空间内放入1 再把a指向的内存空间里的数读出来放到b指向的内存空间, 最后再把b指向的内存空间里的数读出来放到c指向的内存空间里. 然而编译器要对这个程序进行一定的优化,编译的时候,直接把1放入三个内存空间中. 这样子在正常运行的时候确实是好事,但是总会有一些特殊的情况发生,比如,一个中断程序突然改变了a的值,那么会发生这样的情况:

C#编译器优化那点事

使用C#编写程序,给最终用户的程序,是需要使用release配置的,而release配置和debug配置,有一个关键区别,就是release的编译器优化默认是启用的. 优化代码开关即optimize开关,和debug开关一起,有以下几种组合. | 编译器开关设置 |C#IL代码质量 | JIT本地代码质量 | | ------------- |:-------------:| -----:| | /optimize- /debug-(默认) | 未优化 | 有优化 | | /optimize-

对String类型的认识以及编译器优化

Java中String不是基本类型,但是有些时候和基本类型差不多,如String b = "tao" ; 可以对变量直接赋值,而不用 new 一个对象(当然也可以用 new). Java中的变量和基本类型的值存放于栈内存,而new出来的对象本身存放于堆内存,指向对象的引用还是存放在栈内存.例如如下的代码: int  i=1; String s =  new  String( "Hello World" ); 变量i和s以及1存放在栈内存,而s指向的对象"H

一个函数返回临时对象引起的编译器优化问题

我们都知道,如果在一个函数调用另一个函数,假设是 main 函数调用 fun 函数,这个 fun 函数返回一个临时类类型变量,那么这个时候编译器就会在 main 函数申请一个空间并生成一个临时对象,通过拷贝构造函数将 fun 返回的临时变量的值拷贝到这个临时对象.我们看如下的代码: #include <iostream> #include <cstring> using namespace std; class Matrix { public: explicit Matrix(do

深入理解JVM读书笔记四: (早期)编译器优化

10.1概述 Java 语言的 "编译期" 其实是一段 "不确定" 的操作过程,因为它可能是指一个前端编译器(其实叫 "编译器的前端" 更准确一些)把 .java 文件转变成 .class 文件的过程:也可能是指虚拟机的后端运行期编译器(JIT 编译器,Just In Time Compiler)把字节码转变成机器码的过程:还可能是指使用静态提前编译器(AOT 编译器,Ahead Of Time Compiler)直接把 *.java 文件编译成

编译器,优化,及目标代码生成.

本文介绍从源文件开始到目标代码生成的过程. 首先,是我们每天都要接触的源文件.源文件是由纯ASCII或者其他字符集组成的文本,由程序员使用文本编辑器创建.它有以下的几种形式 纯文本.好处是易于维护.并且可以使用处理文本文件的程序来处理源文件. 这个就是我们最常见的源代码形式了.甚至可以使用notepad来处理源文件! 记号化的源文件.使用专门的单字节"记号"值来表示源文件中的保留字等语句元素. 好处1:尺寸小,由于使用单字节的符号来"压缩"多字符的保留字,所以比纯文

[Inside HotSpot] C1编译器优化:条件表达式消除

1. 条件传送指令 日常编程中有很多根据某个条件对变量赋不同值这样的模式,比如: int cmov(int num) { int result = 10; if(num<10){ result = 1; }else{ result = 0; } return result; } 如果不进行编译优化会产出cmp-jump组合,即根据cmp比较的结果进行跳转.可以使用gcc -O0查看: cmov(int): push rbp mov rbp, rsp mov DWORD PTR [rbp-20],

ollvm 编译器优化的bug

近来用ollvm来编译一些代码,主要是需要对so进行一些混淆的操作,发现了一个bug,记录如下: 代码段1 jint begin_antidebug() {     pthread_t antidebugtid;     int ret = 0;     ret = pthread_create(&antidebugtid, NULL, antidebug_listen_thread, NULL);     if(ret!=0)     {         LOGANTI("Create