posts - 319, comments - 22, trackbacks - 0, articles - 11
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

     摘要: 原文:http://ideapad.zol.com.cn/56/160_557421.html本楼层 是虚拟机设置贴子一楼是 Mac安装帖子二楼是 工具下载位置,希望童鞋不要和我抢沙发神舟A560P i7-D2(Windows 7 X64环境下,VMware 8.0正式版)虚拟机首尝MAC OS X 10.7 Lion系统成功,特将此好消息分享。2年了,终于我也装上了Mac,我也成功的尝...  阅读全文

posted @ 2012-04-07 07:30 RTY 阅读(1428) | 评论 (0)编辑 收藏

今天偶然写了下面的程序(原来我写的程序不一样,下面的只是为了把问题简化)

 

  1. void foo()  
  2. {  
  3.     int p = 0;  
  4.     if ( p == 0 )  
  5.         int i = 0;  
  6.     int a;  
  7. }  
  8.   
  9. int main()  
  10. {  
  11.     foo();  
  12. }  
  本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/fancylea/archive/2009/06/10/4256793.aspx 

 

 

不幸的是偶然将这个文件保存成了test.c,然后编译的时候出现了

 

error, error C2143: syntax error : missing ';' before 'type'

 

感觉很奇怪,细细看来所有的语法都似乎都是对的,更奇怪的是把文件改成cpp或者cc能正常编译,把int a;和if调换下也能正常编译。这样的错误可能发生在当变量的声明放在可执行代码之后。而这个是在K&R C中规定的,但在ANSI C中废除。

MSDN (http://support.microsoft.com/kb/58559)给出的解释如下:

 


 

In Microsoft C, compiler errors C2143 and C2144 are defined as follows:

    C2143: syntax error : missing 'token1' before 'token2'
    C2144: syntax error : missing 'token' before type 'type'

 

You may receive this error message if your program places executable code before a data declaration, an acceptable practice in Kernighan-and-Ritchie C. This practice has been outlawed in later versions of the ANSI drafts. 

This error message will normally occur if a required closing curly brace (}), right parenthesis [)], or semicolon (;) is missing.


 

注: The C Programming Language的作者简称K&R,也是C语言之父, 经常用K&R C来和ANSI C做对比。这本书的第二版已经用ANSI.

我用的编译器是VS2008, 看来微软向来无视标准。

 

总结:

在 ANSI C或者C++中,在可执行代码中随时定义变量是允许的,但是在K&R C中是不允许的,VS2008实现的C竟然是K&R C。注意这样的错误也体现在VS中要是用for (int i = 0; i++; i<10)同时你的文件名是.c的也会出现这样的错误。

 

Code complete中讨论过变量名的最迟绑定有利于增加代码的可读性等。所以在VS中写c要注意了。

posted @ 2012-04-05 19:53 RTY 阅读(1832) | 评论 (0)编辑 收藏

请说出const与#define 相比,有何优点?
答案:
1) const 常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查。而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误。
      2) 有些集成化的调试工具可以对const 常量进行调试,但是不能对宏常量进行调试。

在8086 汇编下,逻辑地址和物理地址是怎样转换的?(Intel)
答案:通用寄存器给出的地址,是段内偏移地址,相应段寄存器地址*10H+通用寄存器内地址,就得到了真正要访问的地址。

当一个类A 中没有生命任何成员变量与成员函数,这时sizeof(A)的值是多少,如果不是零,请解释一下编译器为什么没有让它为零。(Autodesk)
答案:肯定不是零。举个反例,如果是零的话,声明一个class A[10]对象数组,而每一个对象占用的空间是零,这时就没办法区分A[0],A[1]…了。

 描述内存分配方式以及它们的区别?
1) 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static 变量
2) 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集。
3) 从堆上分配亦称动态内存分配。程序在运行的时候用malloc 或new 申请任意多少的内存,程序员自己负责在何时用free 或delete 释放内存。动态内存的生存期由程序员决定,使用非常灵活,但问题也最多。

 main 函数执行以前,还会执行什么代码?
答案:全局对象的构造函数会在main 函数之前执行。

 C++是不是类型安全的?
答案:不是。两个不同类型的指针之间可以强制转换(用reinterpret cast)。C#是类型安全的。

 

有哪几种情况只能用intialization list 而不能用assignment?

 

答案:当类中含有const、reference 成员变量;基类的构造函数都需要初始化表。

define DOUBLE(x) x+x ,i = 5*DOUBLE(5); i 是多少?
答案:i 为30

New delete 与malloc free 的联系与区别?
答案:都是在堆(heap)上进行动态的内存操作。用malloc函数需要指定内存分配的字节数并且不能初始化对象,new 会自动调用对象的构造函数。delete 会调用对象的destructor,而free 不会调用对象的destructor.

 

1、写一个“标准”宏,这个宏输入两个参数并返回较小的一个。
.#define Min(X, Y) ((X)>(Y)?(Y):(X))//结尾没有;
2、嵌入式系统中经常要用到无限循环,你怎么用C编写死循环。
while(1){}或者for(;;)
3、关键字static的作用是什么?
定义静态变量
4、关键字const有什么含意?
表示常量不可以修改的变量。
5、关键字volatile有什么含意?并举出三个不同的例子?
提示编译器对象的值可能在编译器未监测到的情况下改变。

 


int (*s[10])(int) 表示的是什么啊
int (*s[10])(int) 函数指针数组,每个指针指向一个int func(int param)的函数。

 


1.有以下表达式:
int a=248; b=4;int const c=21;const int *d=&a;
int *const e=&b;int const *f const =&a;
请问下列表达式哪些会被编译器禁止?为什么?
*c=32;d=&b;*d=43;e=34;e=&a;f=0x321f;
*c 这是个什么东东,禁止
*d 说了是const, 禁止
e = &a 说了是const 禁止
const *f const =&a; 禁止
2.交换两个变量的值,不使用第三个变量。即a=3,b=5,交换之后a=5,b=3;
有两种解法, 一种用算术算法, 一种用^(异或)
a = a + b;
b = a - b;
a = a - b; 
or
a = a^b;// 只能对int,char..
b = a^b;
a = a^b;
or
a ^= b ^= a;
3.c和c++中的struct有什么不同?
c和c++中struct的主要区别是c中的struct不可以含有成员函数,而c++中的struct可以。c++中struct和class的主要区别在于默认的存取权限不同,struct默认为public,而class默认为private
4.#i nclude <stdio.h>
#i nclude <stdlib.h>
void getmemory(char *p)
{
    p=(char *) malloc(100);
    strcpy(p,"hello world");
}
int main( )
{
    char *str=NULL;
    getmemory(str);
    printf("%s/n",str);
    free(str);
    return 0;
   }
程序崩溃,getmemory中的malloc 不能返回动态内存, free()对str操作很危险
5.char szstr[10];
strcpy(szstr,"0123456789");
产生什么结果?为什么?
长度不一样,会造成非法的OS
6.列举几种进程的同步机制,并比较其优缺点。
   原子操作 
信号量机制
   自旋锁
   管程,会合,分布式系统

 

7.进程之间通信的途径
共享存储系统
消息传递系统
管道:以文件系统为基础
11.进程死锁的原因
资源竞争及进程推进顺序非法
12.死锁的4个必要条件
互斥、请求保持、不可剥夺、环路
13.死锁的处理
鸵鸟策略、预防策略、避免策略、检测与解除死锁
15.   操作系统中进程调度策略有哪几种?
FCFS(先来先服务),优先级,时间片轮转,多级反馈
8.类的静态成员和非静态成员有何区别?
类的静态成员每个类只有一个,非静态成员每个对象一个
9.纯虚函数如何定义?使用时应注意什么?
virtual void f()=0;
是接口,子类必须要实现
10.数组和链表的区别
数组:数据顺序存储,固定大小
连表:数据可以随机存储,大小可动态改变

 

12.ISO的七层模型是什么?tcp/udp是属于哪一层?tcp/udp有何优缺点?
应用层
表示层
会话层
运输层
网络层
物理链路层
物理层
tcp /udp属于运输层
TCP 服务提供了数据流传输、可靠性、有效流控制、全双工操作和多路复用技术等。
与 TCP 不同, UDP 并不提供对 IP 协议的可靠机制、流控制以及错误恢复功能等。由于 UDP 比较简单, UDP 头包含很少的字节,比 TCP 负载消耗少。
tcp: 提供稳定的传输服务,有流量控制,缺点是包头大,冗余性不好
udp: 不提供稳定的服务,包头小,开销小  

 


1:(void *)ptr 和 (*(void**))ptr的结果是否相同?其中ptr为同一个指针
.(void *)ptr 和 (*(void**))ptr值是相同的
2:int main()
   {
    int x=3;
    printf("%d",x);
    return 1;
   
   }
问函数既然不会被其它函数调用,为什么要返回1?
mian中,c标准认为0表示成功,非0表示错误。具体的值是某中具体出错信息

 


1,要对绝对地址0x100000赋值,我们可以用
(unsigned int*)0x100000 = 1234;
那么要是想让程序跳转到绝对地址是0x100000去执行,应该怎么做?
*((void (*)( ))0x100000 ) ( );
首先要将0x100000强制转换成函数指针,即:
(void (*)())0x100000
然后再调用它:
*((void (*)())0x100000)();
用typedef可以看得更直观些:
typedef void(*)() voidFuncPtr;
*((voidFuncPtr)0x100000)();
2,已知一个数组table,用一个宏定义,求出数据的元素个数
#define NTBL
#define NTBL (sizeof(table)/sizeof(table[0]))

 

面试题: 线程与进程的区别和联系? 线程是否具有相同的堆栈? dll是否有独立的堆栈?
进程是死的,只是一些资源的集合,真正的程序执行都是线程来完成的,程序启动的时候操作系统就帮你创建了一个主线程。

 

每个线程有自己的堆栈。
DLL中有没有独立的堆栈,这个问题不好回答,或者说这个问题本身是否有问题。因为DLL中的代码是被某些线程所执行,只有线程拥有堆栈,如果DLL中的代码是EXE中的线程所调用,那么这个时候是不是说这个DLL没有自己独立的堆栈?如果DLL中的代码是由DLL自己创建的线程所执行,那么是不是说DLL有独立的堆栈?

 

以上讲的是堆栈,如果对于堆来说,每个DLL有自己的堆,所以如果是从DLL中动态分配的内存,最好是从DLL中删除,如果你从DLL中分配内存,然后在EXE中,或者另外一个DLL中删除,很有可能导致程序崩溃

 


unsigned short A = 10;
printf("~A = %u\n", ~A);

 

char c=128; 
printf("c=%d\n",c);

 

输出多少?并分析过程
第一题,~A =0xfffffff5,int值 为-11,但输出的是uint。所以输出4294967285
第二题,c=0x10,输出的是int,最高位为1,是负数,所以它的值就是0x00的补码就是128,所以输出-128。
这两道题都是在考察二进制向int或uint转换时的最高位处理。

 

分析下面的程序:
void GetMemory(char **p,int num)
{
    *p=(char *)malloc(num);
    
}        
int main()
{
    char *str=NULL;
    
    GetMemory(&str,100);
    
    strcpy(str,"hello");
    
    free(str);
    
    if(str!=NULL)
    {
        strcpy(str,"world");
    }    
        
    printf("\n str is %s",str);
    getchar();
}    
问输出结果是什么?希望大家能说说原因,先谢谢了
输出str is world。
free 只是释放的str指向的内存空间,它本身的值还是存在的.
所以free之后,有一个好的习惯就是将str=NULL.
此时str指向空间的内存已被回收,如果输出语句之前还存在分配空间的操作的话,这段存储空间是可能被重新分配给其他变量的,
尽管这段程序确实是存在大大的问题(上面各位已经说得很清楚了),但是通常会打印出world来。
这是因为,进程中的内存管理一般不是由操作系统完成的,而是由库函数自己完成的。
当你malloc一块内存的时候,管理库向操作系统申请一块空间(可能会比你申请的大一些),然后在这块空间中记录一些管理信息(一般是在你申请的内存前面一点),并将可用内存的地址返回。但是释放内存的时候,管理库通常都不会将内存还给操作系统,因此你是可以继续访问这块地址的,只不过。。。。。。。。楼上都说过了,最好别这么干。

 

char a[10],strlen(a)为什么等于15?运行的结果

 

#i nclude "stdio.h"
#i nclude "string.h"

 

void main()
{

 

char aa[10];
printf("%d",strlen(aa));
}

 

sizeof()和初不初始化,没有关系;
strlen()和初始化有关。

 


char (*str)[20];/*str是一个数组指针,即指向数组的指针.*/
char *str[20];/*str是一个指针数组,其元素为指针型数据.*/

 

long a=0x801010;
a+5=?
0x801010用二进制表示为:“1000 0000 0001 0000 0001 0000”,十进制的值为8392720,再加上5就是8392725罗

 

1)给定结构struct A 
{
       char t:4;
       char k:4;
       unsigned short i:8;
       unsigned long m;
};问sizeof(A) = ?
给定结构struct A 
{
       char t:4; 4位
       char k:4; 4位
       unsigned short i:8; 8位      
       unsigned long m; // 偏移2字节保证4字节对齐
}; // 共8字节
2)下面的函数实现在一个数上加一个数,有什么错误?请改正。
int add_n ( int n )
{
    static int i = 100;
    i += n;
    return i;
}
当你第二次调用时得不到正确的结果,难道你写个函数就是为了调用一次?问题就出在 static上?

 


// 帮忙分析一下
#i nclude<iostream.h>
#i nclude <string.h>
#i nclude <malloc.h>
#i nclude <stdio.h>
#i nclude <stdlib.h>
#i nclude <memory.h>
typedef struct AA
{
        int b1:5;
        int b2:2;
}AA;
void main()
{
        AA aa;
        char cc[100];
         strcpy(cc,"0123456789abcdefghijklmnopqrstuvwxyz");
       memcpy(&aa,cc,sizeof(AA));
        cout << aa.b1 <<endl;
        cout << aa.b2 <<endl;
}
答案是 -16和1
首先sizeof(AA)的大小为4,b1和b2分别占5bit和2bit.
经过strcpy和memcpy后,aa的4个字节所存放的值是:
0,1,2,3的ASC码,即00110000,00110001,00110010,00110011
所以,最后一步:显示的是这4个字节的前5位,和之后的2位
分别为:10000,和01
因为int是有正负之分  所以:答案是-16和1

 

求函数返回值,输入x=9999; 
int func ( x )

    int countx = 0; 
    while ( x ) 
    { 
        countx ++; 
        x = x&(x-1); 
    } 
    return countx; 

结果呢?
知道了这是统计9999的二进制数值中有多少个1的函数,且有
9999=9×1024+512+256+15

 

9×1024中含有1的个数为2;
512中含有1的个数为1;
256中含有1的个数为1;
15中含有1的个数为4;
故共有1的个数为8,结果为8。
1000 - 1 = 0111,正好是原数取反。这就是原理。
用这种方法来求1的个数是很效率很高的。
不必去一个一个地移位。循环次数最少。

 

int a,b,c 请写函数实现C=a+b ,不可以改变数据类型,如将c改为long int,关键是如何处理溢出问题
bool add (int a, int b,int *c)
{
*c=a+b;
return (a>0 && b>0 &&(*c<a || *c<b) || (a<0 && b<0 &&(*c>a || *c>b)));
}

 


分析:
struct bit 
{   int a:3; 
    int b:2; 
    int c:3; 
}; 
int main() 

bit s; 
char *c=(char*)&s; 
   cout<<sizeof(bit)<<endl;
*c=0x99;
   cout << s.a <<endl <<s.b<<endl<<s.c<<endl; 
     int a=-1;
   printf("%x",a);
return 0; 

输出为什么是
4
1
-1
-4
ffffffff
因为0x99在内存中表示为 100 11 001 , a = 001, b = 11, c = 100
当c为有符合数时, c = 100, 最高1为表示c为负数,负数在计算机用补码表示,所以c = -4;同理 
b = -1;
当c为有符合数时, c = 100,即 c = 4,同理 b = 3

 


位域 :   
有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几个不同的区域, 并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。 这样就可以把几个不同的对象用一个字节的二进制位域来表示。一、位域的定义和位域变量的说明位域定义与结构定义相仿,其形式为:     
struct 位域结构名     
{ 位域列表 };    
其中位域列表的形式为: 类型说明符 位域名:位域长度     
例如:     
struct bs    
{    
int a:8;    
int b:2;    
int c:6;    
};    
位域变量的说明与结构变量说明的方式相同。 可采用先定义后说明,同时定义说明或者直接说明这三种方式。例如:     
struct bs    
{    
int a:8;    
int b:2;    
int c:6;    
}data;    
说明data为bs变量,共占两个字节。其中位域a占8位,位域b占2位,位域c占6位。对于位域的定义尚有以下几点说明:   

 

1. 一个位域必须存储在同一个字节中,不能跨两个字节。如一个字节所剩空间不够存放另一位域时,应从下一单元起存放该位域。也可以有意使某位域从下一单元开始。例如:     
struct bs    
{    
unsigned a:4    
unsigned :0 /*空域*/    
unsigned b:4 /*从下一单元开始存放*/    
unsigned c:4    
}    
在这个位域定义中,a占第一字节的4位,后4位填0表示不使用,b从第二字节开始,占用4位,c占用4位。   

 

2. 由于位域不允许跨两个字节,因此位域的长度不能大于一个字节的长度,也就是说不能超过8位二进位。   

 

3. 位域可以无位域名,这时它只用来作填充或调整位置。无名的位域是不能使用的。例如:     
struct k    
{    
int a:1    
int :2 /*该2位不能使用*/    
int b:3    
int c:2    
};    
从以上分析可以看出,位域在本质上就是一种结构类型, 不过其成员是按二进位分配的。   

 

二、位域的使用位域的使用和结构成员的使用相同,其一般形式为: 位域变量名•位域名 位域允许用各种格式输出。    
main(){    
struct bs    
{    
unsigned a:1;    
unsigned b:3;    
unsigned c:4;    
} bit,*pbit;    
bit.a=1;    
bit.b=7;    
bit.c=15;    
pri

 

改错:
#i nclude <stdio.h>

 

int main(void) {

 

    int **p;
    int arr[100];

 

    p = &arr;

 

    return 0;
}
解答:
搞错了,是指针类型不同,
int **p; //二级指针
&arr; //得到的是指向第一维为100的数组的指针
#i nclude <stdio.h>
int main(void) {
int **p, *q;
int arr[100];
q = arr;
p = &q;
return 0;
}

 


下面这个程序执行后会有什么错误或者效果:
#define MAX 255
int main()
{
   unsigned char A[MAX],i;//i被定义为unsigned char
   for (i=0;i<=MAX;i++)
      A[i]=i;
}
解答:死循环加数组越界访问(C/C++不进行数组越界检查)
MAX=255 
数组A的下标范围为:0..MAX-1,这是其一..
其二.当i循环到255时,循环内执行:
A[255]=255;
这句本身没有问题..但是返回for (i=0;i<=MAX;i++)语句时,
由于unsigned char的取值范围在(0..255),i++以后i又为0了..无限循环下去.

 

struct name1{
   char str;
   short x;
   int   num;
}

 

struct name2{
   char str;
   int num;
   short x;
}

 

sizeof(struct name1)=8,sizeof(struct name2)=12
在第二个结构中,为保证num按四个字节对齐,char后必须留出3字节的空间;同时为保证整个结构的自然对齐(这里是4字节对齐),在x后还要补齐2个字节,这样就是12字节。

 

intel:
A.c 和B.c两个c文件中使用了两个相同名字的static变量,编译的时候会不会有问题?这两个static变量会保存到哪里(栈还是堆或者其他的)?
static的全局变量,表明这个变量仅在本模块中有意义,不会影响其他模块。
他们都放在数据区,但是编译器对他们的命名是不同的。
如果要使变量在其他模块也有意义的话,需要使用extern关键字。

 

struct s1
{
int i: 8;
int j: 4;
int a: 3;
double b;
};

 

struct s2
{
int i: 8;
int j: 4;
double b;
int a:3;
};

 

printf("sizeof(s1)= %d\n", sizeof(s1));
printf("sizeof(s2)= %d\n", sizeof(s2));
result: 16, 24
第一个struct s1
{
int i: 8;
int j: 4;
int a: 3;
double b;
};
理论上是这样的,首先是i在相对0的位置,占8位一个字节,然后,j就在相对一个字节的位置,由于一个位置的字节数是4位的倍数,因此不用对齐,就放在那里了,然后是a,要在3位的倍数关系的位置上,因此要移一位,在15位的位置上放下,目前总共是18位,折算过来是2字节2位的样子,由于double是8字节的,因此要在相对0要是8个字节的位置上放下,因此从18位开始到8个字节之间的位置被忽略,直接放在8字节的位置了,因此,总共是16字节。

 

第二个最后会对照是不是结构体内最大数据的倍数,不是的话,会补成是最大数据的倍数

 

上面是基本问题,接下来是编程问题:

 


本人很弱,这几个题也搞不定,特来求救:
1)读文件file1.txt的内容(例如):
12
34
56
输出到file2.txt:
56
34
12
(逆序)
2)输出和为一个给定整数的所有组合
例如n=5
5=1+4;5=2+3(相加的数不能重复)
则输出
1,4;2,3。
望高手赐教!!

 

第一题,注意可增长数组的应用.
#i nclude <stdio.h>
#i nclude <stdlib.h>

 

int main(void)
{
         int MAX = 10;
int *a = (int *)malloc(MAX * sizeof(int));
int *b;
    
FILE *fp1;
FILE *fp2;

 

fp1 = fopen("a.txt","r");
if(fp1 == NULL)
{printf("error1");
    exit(-1);
}

 

    fp2 = fopen("b.txt","w");
if(fp2 == NULL)
{printf("error2");
    exit(-1);
}

 

int i = 0;
    int j = 0;

 

while(fscanf(fp1,"%d",&a[i]) != EOF)
{
i++;
j++;
if(i >= MAX)
{
MAX = 2 * MAX;
b = (int*)realloc(a,MAX * sizeof(int));
if(b == NULL)
{
printf("error3");
exit(-1);
}
a = b;
}
}

 

for(;--j >= 0;)
   fprintf(fp2,"%d\n",a[j]);

 

fclose(fp1);
fclose(fp2);

 

return 0;
}

 

第二题.
#i nclude <stdio.h>

 

int main(void)
{
unsigned long int i,j,k;

 

printf("please input the number\n");
scanf("%d",&i);
    if( i % 2 == 0)
        j = i / 2;
else
j = i / 2 + 1;

 

printf("The result is \n");
    for(k = 0; k < j; k++)
     printf("%d = %d + %d\n",i,k,i - k);
return 0;
}

 

#i nclude <stdio.h>
void main()
{
unsigned long int a,i=1;
scanf("%d",&a);
if(a%2==0)
{
     for(i=1;i<a/2;i++)
     printf("%d",a,a-i);
}
else
for(i=1;i<=a/2;i++)
        printf(" %d, %d",i,a-i);
}

 

兄弟,这样的题目若是做不出来实在是有些不应该, 给你一个递规反向输出字符串的例子,可谓是反序的经典例程.

 

void inverse(char *p)
{
    if( *p = = '\0' ) 
return;
    inverse( p+1 );
    printf( "%c", *p );
}

 

int main(int argc, char *argv[])
{
    inverse("abc\0");

 

    return 0;
}

 

借签了楼上的“递规反向输出”
#i nclude <stdio.h>
void test(FILE *fread, FILE *fwrite)
{
        char buf[1024] = {0};
        if (!fgets(buf, sizeof(buf), fread))
}



posted @ 2012-04-05 14:54 RTY 阅读(740) | 评论 (0)编辑 收藏

http://www.cppblog.com/lf426/archive/2008/03/19/44831.html 

作者:龙飞

1:扩充库(Extension Libraries)

        SDL本身所支持的,仅仅是读取bmp格式的图片。要使用其它格式的图片,我们需要使用SDL的扩充库。在下面地址,我们可以下载到相关文件SDL_image-devel-1.2.6-VC8.zip
http://www.libsdl.org/projects/SDL_image/
        与SDL本身的设置一样,将include下的*.h文件拷贝到:
C:\MinGW\include\SDL (MinGW)
C:\Program Files\Microsoft Visual Studio 9.0\VC\include\SDL (VC2008)
        将*.lib文件拷贝到:
C:\MinGW\lib (MinGW)
C:\Program Files\Microsoft Visual Studio 9.0\VC\lib (VC2008)
        将*.dll文件拷贝到:
C:\WINDOWS\system32

        在编译的时候,gcc注意增加共同编译的库文件-lSDL_image,比如,我设置了一个批处理文件g++img.bat内容如下:
g++ -o MySDL.exe main.cpp -lmingw32 -lSDLmain -lSDL -lSDL_image -mwindows
        在VC2008中,需要在projec属性中,Configuration Properties -- Linker -- Input -- Additional Dependencies 下增加SDL_image.lib。

        在程序的头文件中,需要增加:
#include "SDL/SDL_image.h"

2:更加通用的Display Surface构造函数

        我们现在可以回头过来修改我们在SDL入门教程(五):6、对C++异常机制的思考,代码重写中的Display Surface类的构造函数,使其能够更加通用的读取其它格式的图片。
DisplaySurface::DisplaySurface(std::string file_name, const ScreenSurface& screen):
fileName(file_name)
{
    SDL_Surface
* pSurfaceTemp = IMG_Load(file_name.c_str());
    
if ( pSurfaceTemp == 0 )
        
throw ErrorInfo(SDL_GetError());
    pSurface 
= SDL_DisplayFormat(pSurfaceTemp);
    
if ( pSurface == 0 )
        
throw ErrorInfo(SDL_GetError());
    SDL_FreeSurface(pSurfaceTemp);
    pScreen 
= screen.point();
}
        IMG_Load()可以读取多种格式的图片文件,包括BMP, PNM, XPM, LBM, PCX, GIF, JPEG, TGA和PNG。

3:将图片修改为适合显示的格式
SDL_Surface *SDL_DisplayFormat(SDL_Surface *surface);
        在上面的程序中,我们使用到了函数SDL_DisplayFormat()。在之前的教程中,我一直没有用到这个函数,是因为我还没有发现用SDL_LoadBMP()的时候会出现格式兼容性的问题——即使是图片位深与显示不一致。但是使用IMG_Load()的时候,小小的bug出现了。所以,这里我必须使用SDL_DisplayFormat(),将读取的图片文件转换为适合显示的格式。
        如果转换失败,或者内存溢出,这个函数将返回空指针。 

posted @ 2012-04-04 08:25 RTY 阅读(595) | 评论 (0)编辑 收藏

Configure,Makefile.am, Makefile.in, Makefile文件之间关系
2009-08-12 12:14

1.autoscan (autoconf): 扫描源代码以搜寻普通的可移植性问题,比如检查编译器,库,头文件等,生成文件configure.scan,它是configure.ac的一个雏形。

your source files --> [autoscan*] --> [configure.scan] --> configure.ac

2.aclocal (automake):根据已经安装的宏,用户定义宏和acinclude.m4文件中的宏将configure.ac文件所需要的宏集中定义到文件 aclocal.m4中。aclocal是一个perl 脚本程序,它的定义是:“aclocal - create aclocal.m4 by scanning configure.ac”
user input files   optional input     process          output files
================ ============== ======= ============

acinclude.m4 - - - - -.
V
.-------,
configure.ac ------------------------>|aclocal|
{user macro files} ->| |------> aclocal.m4
`-------'
3.autoheader(autoconf): 根据configure.ac中的某些宏,比如cpp宏定义,运行m4,声称config.h.in

user input files optional input process output files
================ ============== ======= ============

aclocal.m4 - - - - - - - .
|
V
.----------,
configure.ac ----------------------->|autoheader|----> autoconfig.h.in
`----------'

4.automake: automake将Makefile.am中定义的结构建立Makefile.in,然后configure脚本将生成的Makefile.in文件转换 为Makefile。如果在configure.ac中定义了一些特殊的宏,比如AC_PROG_LIBTOOL,它会调用libtoolize,否则它 会自己产生config.guess和config.sub

user input files   optional input   processes          output files
================ ============== ========= ============

.--------,
| | - - -> COPYING
| | - - -> INSTALL
| |------> install-sh
| |------> missing
|automake|------> mkinstalldirs
configure.ac ----------------------->| |
Makefile.am ----------------------->| |------> Makefile.in
| |------> stamp-h.in
.---+ | - - -> config.guess
| | | - - -> config.sub
| `------+-'
| | - - - -> config.guess
|libtoolize| - - - -> config.sub
| |--------> ltmain.sh
| |--------> ltconfig
`----------'

5.autoconf:将configure.ac中的宏展开,生成configure脚本。这个过程可能要用到aclocal.m4中定义的宏。

user input files   optional input   processes          output files
================ ============== ========= ============

aclocal.m4 ,autoconfig.h.in - - - - - - -.
V
.--------,
configure.ac ----------------------->|autoconf|------> configure
 
6. ./configure的过程

.-------------> [config.cache]
configure* --------------------------+-------------> config.log
|
[config.h.in] -. v .--> [autoconfig.h]
+-------> config.status* -+
Makefile.in ---' `--> Makefile
 
7. make过程
 
[autoconfig.h] -.
+--> make* ---> 程序
Makefile ---'
 
.---------,
config.site - - ->| |
config.cache - - ->|configure| - - -> config.cache
| +-,
`-+-------' |
| |----> config.status
config.h.in ------->|config- |----> config.h
Makefile.in ------->| .status|----> Makefile
| |----> stamp-h
| +--,
.-+ | |
| `------+--' |
ltmain.sh ------->|ltconfig|-------> libtool
| | |
`-+------' |
|config.guess|
| config.sub |
`------------'

.--------,
Makefile ------>| |
config.h ------>| make |
{project sources} ---------------->| |--------> {project targets}
.-+ +--,
| `--------' |
| libtool |
| missing |
| install-sh |
|mkinstalldirs|
`-------------'
实例:
在/hello/目录下创建一个hello.c文件,并编译运行它:

#cd /hello/

(1) 编写源文件hello.c:

#include<stdio.h>
int main(int argc, char** argv)
{
printf("Hello, GNU!n");
return 0;
}

[litao@vm0000131 hello]$ ll
total 4
-rw-rw-r-- 1 litao litao 68 Aug 12 12:02 hello.c

一、autoscan

[litao@vm0000131 hello]$ autoscan
autom4te: configure.ac: no such file or directory
autoscan: /usr/bin/autom4te failed with exit status: 1
[litao@vm0000131 hello]$ ll
total 8
-rw-rw-r-- 1 litao litao 0 Aug 12 12:03 autoscan.log
-rw-rw-r-- 1 litao litao 457 Aug 12 12:03 configure.scan
-rw-rw-r-- 1 litao litao 68 Aug 12 12:02 hello.c

已经生成了configure.scan,autoscan.log文件

将configure.scan 修改为 configure.in,最后修改的内容如下:

[litao@vm0000131 hello]$ mv configure.scan configure.in
[litao@vm0000131 hello]$ vim configure.in

# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ(2.59)
AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)
AC_CONFIG_SRCDIR([hello.c])
#AC_CONFIG_HEADER([config.h])
AM_INIT_AUTOMAKE(hello, 1.0)
# Checks for programs.
AC_PROG_CC

# Checks for libraries.

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.
AC_OUTPUT(Makefile)

二、acloacl

[litao@vm0000131 hello]$ aclocal

生成 aclocal.m4 和 autom4te.cache (生成aclocal.m4的过程中涉及到configure.in)

[litao@vm0000131 hello]$ ll
total 44
-rw-rw-r-- 1 litao litao 31120 Aug 12 12:08 aclocal.m4
drwxr-xr-x 2 litao litao 4096 Aug 12 12:08 autom4te.cache
-rw-rw-r-- 1 litao litao 0 Aug 12 12:03 autoscan.log
-rw-rw-r-- 1 litao litao 496 Aug 12 12:08 configure.in
-rw-rw-r-- 1 litao litao 68 Aug 12 12:02 hello.c

三、antoconf

[litao@vm0000131 hello]$ autoconf
生成 configure (根据 configure.in, 和 aclocal.m4)
[litao@vm0000131 hello]$ ll
total 168
-rw-rw-r-- 1 litao litao 31120 Aug 12 12:08 aclocal.m4
drwxr-xr-x 2 litao litao 4096 Aug 12 12:11 autom4te.cache
-rw-rw-r-- 1 litao litao 0 Aug 12 12:03 autoscan.log
-rwxrwxr-x 1 litao litao 122297 Aug 12 12:11 configure
-rw-rw-r-- 1 litao litao 496 Aug 12 12:08 configure.in
-rw-rw-r-- 1 litao litao 68 Aug 12 12:02 hello.c

四、编写Makefile.am:

AUTOMAKE_OPTIONS= foreign
bin_PROGRAMS= hello
hello_SOURCES= hello.c

五、automake

生成 Makefile.in, depcomp, install-sh, 和 missing (根据 Makefile.am, 和 aclocal.m4)

[litao@vm0000131 hello]$ automake
configure.in: required file `./install-sh' not found
configure.in: required file `./missing' not found
Makefile.am: required file `./depcomp' not found
[litao@vm0000131 hello]$ automake --add-missing
configure.in: installing `./install-sh'
configure.in: installing `./missing'
Makefile.am: installing `./depcomp'
[litao@vm0000131 hello]$ ll
total 192
-rw-rw-r-- 1 litao litao 31120 Aug 12 12:08 aclocal.m4
drwxr-xr-x 2 litao litao 4096 Aug 12 12:14 autom4te.cache
-rw-rw-r-- 1 litao litao 0 Aug 12 12:03 autoscan.log
-rwxrwxr-x 1 litao litao 122297 Aug 12 12:11 configure
-rw-rw-r-- 1 litao litao 496 Aug 12 12:08 configure.in
lrwxrwxrwx 1 litao litao 31 Aug 12 12:16 depcomp -> /usr/share/automake-1.9/depcomp
-rw-rw-r-- 1 litao litao 68 Aug 12 12:02 hello.c
lrwxrwxrwx 1 litao litao 34 Aug 12 12:16 install-sh -> /usr/share/automake-1.9/install-sh
-rw-rw-r-- 1 litao litao 69 Aug 12 12:15 Makefile.am
-rw-rw-r-- 1 litao litao 16561 Aug 12 12:16 Makefile.in
lrwxrwxrwx 1 litao litao 31 Aug 12 12:16 missing -> /usr/share/automake-1.9/missing

六、configure
生成 Makefile, config.log, 和 config.status


posted @ 2012-04-03 22:20 RTY 阅读(794) | 评论 (0)编辑 收藏

导读:

/C:在预处理输出中保留注释语句
/c:只编译,不连接,相当于在"Build"菜单下选择了"Compile"
/D:定义常量和宏,与源程序里的#define 有相同效果
/E:预处理C、C++源文件,将源文件中所有的预编译指令及宏展开,将注释去掉,然后将预处理器的输出拷贝至标准输出设备输出,并且在每个文件的开头和末尾加入#line
/EH:指定编译器用何种异常处理模型
/EP:同/E,只是去掉了#line
/F:设置程序的堆栈大小
/FA:设置生成何种列表文件(汇编、汇编与机器码、汇编与源码、汇编与机器码以及源码)
/Fa:指定用/FA设置的列表文件的存放路径及(或)文件名
/FD:生成文件的相互依赖信息
/Fd:设置程序数据库文件(PDB)的存放路径及(或)文件名
/Fe:设置最终可执行文件的存放路径及(或)文件名
/FI:预处理指定的头文件,与源文件中的#include有相同效果
/Fm:创建map文件
/Fo:设置编译后Obj文件的存放路径及(或)文件名
/Fp:设置预编译文件(pch)的存放路径及(或)文件名
/FR:生成浏览信息(sbr)文件
/Fr:同/FR,不同之处在于/Fr不包括局部变量信息
/G3:为80386处理器优化代码生成
/G4:为80486处理器优化代码生成
/G5:为Pentium处理器优化代码生成
/G6:为Pentium Pro处理器优化代码生成
/GA:为Windows应用程序作优化
/GB:为Pentium处理器优化代码生成,使用80386、80486、Pentium、Pentium Pro的混合指令集,是代码生成的默认选项(程序属性选项中Processor对应Blend)
/GD:为Windows动态库(dll)作优化,此开关在VC6中没有实现
/Gd:指定使用__cdecl的函数调用规则
/Ge:激活堆栈检测
/GF:消除程序中的重复的字符串,并将她放到只读的缓冲区中
/Gf:消除程序中的重复字符串
/Gh:在每个函数的开头调用钩子(hook)函数--penter
/Gi:允许渐进编译
/Gm:允许最小化rebuild
/GR:允许运行时类型信息(Run-Time Type Infomation)
/Gr:指定使用__fastcall的函数调用规则
/Gs:控制堆栈检测所用内存大小
/GT:支持用__declspec(thread)分配的数据的fier-safety
/GX:允许同步异常处理,与/EHsc开关等价
/Gy:允许编译器将每一个函数封装成COMDATs的形式,供连接器调用
/GZ:允许在Debug build 的时候捕捉Release build的错误
/Gz:指定使用__stdcall的函数调用规则
/H:限制外部名字的长度
/HELP:列出编译器的所有的命令开关
/I:指定头文件的搜索路径
/J:将char的缺省类型从signed char改成unsigned char
/LD:创建一个动态连接库
/LDd:创建一个Debug版本的动态链接库
/link:将指定的选项传给连接器
/MD:选择多线程、DLL版本的C Run-Time库
/MDd:选择多线程、DLL、Debug版本的C Run-Time库
/ML:选择单线程版本的C Run—Time库
/MLd:选择单线程、Debug版本的C Run—Time库
/MT:选择多线程版本的C Run-Time库
/MTd:选择多线程、Debug版本的C Run—Time库
/nologo:不显示程序的版权信息
/O1:优化使产生的可执行代码最小
/O2:优化使产生的可执行代码速度最快
/Oa:指示编译器程序里没有使用别名,可以提高程序的执行速度
/Ob:控制内联(inline)函数的展开
/Od:禁止代码优化
/Og:使用全局优化
/Oi:用内部函数去代替程序里的函数调用,可以使程序运行的更快,但程序的长度变长
/Op:提高浮点数比较运算的一致性
/Os:产生尽可能小的可执行代码
/Ot:产生尽可能块的可执行代码
/Ow:指示编译器在函数体内部没有使用别名
/Ox:组合了几个优化开关,达到尽可能多的优化
/Oy:阻止调用堆栈里创建帧指针
/Q1f:对核心级的设备驱动程序生成单独的调试信息
/QI0f:对Pentium 0x0f错误指令作修正
/Qifdiv:对Pentium FDIV错误指令作修正
/P:将预处理输出写到指定文件里,文件的后缀名为I
/TC:将命令行上的所有文件都当作C源程序编译,不管后缀名是否为.c
/Tc:将指定的文件当作C源程序编译,不管后缀名是否为.c
/TP:将命令行上的所有文件都当作C++源程序编译,不管后缀名是否为.cpp
/Tp:将指定文件当作C++源程序编译,不管后缀名是否为.cpp
/U:去掉一个指定的前面定义的符号或常量
/u:去掉所有前面定义的符号或常量
/V:在编译的obj文件里嵌入版本号
/vd:禁止/允许构造函数置换
/vmb:选择指针的表示方法,使用这个开关,在声明指向某个类的成员的指针之前,必须先定义这个类
/vmg:选择指针的表示方法,使用这个开关,在声明指向某个类的成员的指针之前,不必先定义这个类,但要首先指定这个类是使用何种继承方法
/vmm:设置指针的表示方法为Single Inheritance and Multiple Inheritance
/vms:设置指针的表示方法为Single Inheritance
/vmv:设置指针的表示方法为Any class
/W:设置警告等级
/w:禁止所有警告
/X:阻止编译器搜索标准的include 目录
/Yc:创建预编译头文件(pch)
/Yd:在所有的obj文件里写上完全的调试信息
/Yu:在build过程中使用指定的预编译头文件
/YX:指示编译器若预编译头文件存在,则使用它,若不存在,则创建一个
/Z7:生成MSC7.0兼容的调试信息
/Za:禁止语言扩展(Microsoft Extensions to C)
/Zd:调试信息只包含外部和全局的符号信息以及行号信息
/Ze:允许语言扩展(Microsoft Extensions to C)
/Zg:为源文件里面定义的每个函数生成函数原型
/ZI:生成程序库文件(Pdb)并支持Edit and Continue调试特性
/Zi:生成程序库文件(pdb),包含类型信息和符号调试信息
/ZL:从obj文件里去掉缺省的库文件名
/Zm:设置编译器的内存分配xianzhi
/Zn:禁止浏览信息文件里面的封装
/Zp:设置结构成员在内存里面的封装格式
/Zs:快速检查语法错误
--------------------------
vc所支持的文件类型


DSW:全称是Developer Studio Workspace,最高级别的配置文件,记录了整个工作空间的配置信息,她是一个纯文本的文件,在vc创建新项目的时候自动生成
DSP:全称是Developer Studio Project,也是一个配置文件,不过她记录的是一个项目的所有配置信息,纯文本文件
OPT:与DSW、DSP配合使用的配置文件,她记录了与机器硬件有关的信息,同一个项目在不同的机器上的opt文件内容是不同的
CLW:记录了跟ClassWizard相关的信息,如果丢失了clw文件,那么在Class View面板里就没有类信息
PLG:实际上是一个超文本文件,可以用Internet Explorer打开,记录了Build的过程,是一个日志型文件
RC:资源描述文件,记录了所有的资源信息,在资源编辑器里作的修改,实际上都是对RC文件的修改
RC2:附加的资源描述文件,不能直接资源编辑器修改,只能手工添加,可以用来添加额外的资源
RES:经过资源编辑器编译之后的资源文件,以二进制方式存放
SBR:编译器生成的浏览信息文件,在代码导航的时候非常有用,她需要在编译时指定/FR或者/Fr开关
BSC:BSCMAKE.EXE将所有的SBR文件作为输入,经过处理之后输出一个BSC文件,在代码导航的时候实际用到的是BSC文件
ILK:当选定渐增型编译连接时,连接器自动生成ILK文件,记录连接信息
PDB:全称是Program DataBase,即程序数据库文件,用来记录调试信息,是一个相当重要的文件,没有他,程序无法正常调试
LIB:如果项目输出是Dll的话,一般会输出一个跟项目同名的Lib文件,记录输出的函数信息
EXP:同Lib,是跟Dll一起生成的输出文件
PCH:全称是PreCompiled Header,就是预先编译好的头文件,在编译时指定/Yu开关时编译器自动生成



本文转自
http://www.cppblog.com/sunraiing9/archive/2007/11/26/37323.html

posted @ 2012-03-30 20:46 RTY 阅读(525) | 评论 (0)编辑 收藏

导读:


版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://chenshine.blogbus.com/logs/4414354.html


刚 进入计算机相关专业领域时,大家最先用过的调试器大多会是Turbo C。它虽然古老但用过的人却很多,然而严格的讲,Turbo C是一个集成开发环境,虽然拥有独立的编译器,链接器,却没有独立的调试器,这和Visual Studio一样。如果你做过DOS,早期Windows下的汇编,也许你会对Debug,CodeView等调试工具熟悉,但这些工具太老 了,Debug甚至不能调试32位程序,介绍它们与这篇文章的主旨不符,如果你对它们感兴趣,可以去查阅相关资料。本文主要是介绍与调试技术相关的理论知 识以及常用调试器的使用,Windows设备驱动程序与内核的调试等。具体的讲解方法是理论结合实践,并且是站在给新手看的角度,循序渐进的,用一个一个 调试会话向你展示每个重要命令的使用。



目录

1。调试器
2。调试信息
3。用户模式程序的调试
4。驱动程序与内核的调试

1 调试器

1。1 概览

调 试器,与编译器,链接器一样,都属于基础软件,它们在制作上都有很大的难度,但尽管如此,现实中还是有不少专业级的调试器,微软官方的就有 cdb,ntsd,WinDbg,kd等,还有SoftIce,OllyDbg等来自于其它公司的优秀调试器。本文不可能对这几个调试器一一介绍,一个是 限于篇幅,另一个是上面列举的这几个调试器无论是哪一个都需要你花很长的时间去完全掌握(在市面上有很多书籍甚至专门讲解某一个调试器的使用,比如 SoftIce)。虽然本文不会讲解SoftIce的详细使用,但我还是要对它进行简短的介绍,因为它太有名了,甚至比Windows出生的早。

1。2 SoftIce

SoftIce 是NuMega公司生产的调试器,产于80年代后期,直到今天为止,这个软件已经变革过好几次了,因为处理器的体系结构在更新,操作系统也在更新,所以调 试器也必须相应的更新。它之所以有名,那是与历史有关的,在Intel推出386 Cpu的时候,NuMega立即让SoftIce支持了386 Cpu的新特性,同时吸引了大量黑客的使用,使它在黑客界产生了一定的地位(功能强大的调试器可以对软件的保护机制进行破解,如突破序列号之类的)。在 Windows推出时,所有的调试器都不适用这种新的系统软件体系结构了,唯一能用的就是微软自己生产的调试器,却很拙劣,这时NuMega又对 SoftIce进行了变革,不仅让它可以在新的系统上很好的工作,甚至还可以调试Windows的内核,这是当时是不敢想象的。也正是因为它很好的性能, 卓越的功能,它成为了黑客们的宠儿,并且培养了几代的黑客。读完本文后,你自己应该有能力去探索它,或许你也可以在这几款调试器里找到适合自己的。

1。3 微软的调试工具

本 文主要介绍的是微软官方的调试器,并且MS微软也最积极,调试工具包一直在更新中。在微软的调试器里,大家可能最为熟悉Visual Studio Debugger,就是你在Visual C++里使用的那个,它并不是一个单独可运行的程序,而是内嵌在Visual Studio中的,它的功能相对于上面几个调试器来说要弱很多,这里并不会对它进行介绍,如果你想全方面的了解它的话,你可以去参考MSDN,那里专门有 几章讲解它,是一份很好的文档化的资源(而且还是中文的)。其它的微软调试工具cdb,ntsd,WinDbg,kd都在微软的一个安装包里,被称作Debugging Tools for Windows(10 多M的大小,请通过这个链接下载并安装,一会儿就要用到)。这些调试器在下文中会分别介绍,这里先做一个简单的区别,cdb与ntsd几乎是一样的程序, 唯一的不同是cdb是一个CUI程序,即Console程序,而ntsd是GUI程序,但ntsd并没有产生窗口,而是又分配了一个Console窗口, 这个Console窗口就相当于是cdb。它与真正的cdb执行完全一样的功能(官方如是说,然而实际上还有一些个不同)。在命令行中启动它们时下面两句 命令有一样的效果(C:/Progs/Debug是调试工具包的安装位置):

C:/Progs/Debug/>start cdb
C:/Progs/Debug/>ntsd

cdb 与ntsd是用来调试用户模式应用程序的。kd调试器也是一个命令行程序,不过正如其名kernel debugger所描述的一样,它是内核调试器的,是驱动程序开发者,系统Hacker的最爱。WinDbg是一个称职的GUI程序,它有菜单,有工具 栏,还有多个子窗口,可以分别显示源代码,调用栈,命令等,它既可以调试ring 0程序,也可以调试ring 3程序,其实它只是一个壳而已,当调试ring 3级程序时它实际上是用cdb/ntsd,而当调试ring 0级程序时是用kd。WinDbg的到来吸引了很多的人使用,你也将会发现,它确实是一款优秀的调试器。

2 调试信息

调试器之所以能够工作,完全是依赖于编译和链接程序时所生成的调试信息,当然调试信息是具有一定的格式的。

2。1 格式

微 软的调试信息格式经过了几代变化,最终形成了Program DataBase这种格式,并且这种格式还在进行版本上的更新,VS.Net所用的新的Program DataBase版本与Visual C++ 6.0所用的老的版本是不兼容的,并且你也可以用编译器和链接器明确指定你想要生成的调试信息格式,这一点下文中有阐述。

2。2 内容

关 于调试信息我们还必须知道两件事,一是调试信息包括哪些内容,二是调试信息储存在什么地方。其实调试信息所应该包括的内容正是调试信息格式变化的原因,从 COFF格式,到CodeView格式,到Program DataBase格式,调试信息变得越来越丰富了,并且是只多不少。Program DataBase格式的调试信息中主要包括了所有全局函数,static 函数,全局变量,static变量,局部变量,函数形参的名字及其位置,源代码与可执行文件中指令的映射信息,每个函数与变量的类型,以及FPO信息,编 辑和继续信息。编辑与继续信息主要用于在Visual Studio中调试时,可以在调试的同时编辑源代码,并在接下来的调试中得到体现。Program DataBase格式的调试信息包含了这么多的内容,所以用这种调试信息来调试程序时,你将能够得到更多,更准确,更深入的反馈。

2。3 存储位置

调 试信息的存储位置是与其格式相关的,Program DataBase格式的调试信息存储在一个单独的文件里,扩展名为pdb。像以前的CodeView格式的调试信息即可存储在单独的文件里,又可存储在编 译时所生成的obj文件中。知道了这些知识后,我们就可以正确地生成调试信息了。在后面的内核调试中我们还要继续谈到它。

3 用户模式程序的调试

根 据上面的讲述,我们可以用cdb或WinDbg来进行ring 3程序的调试,这里先讲解cdb。cdb允许你启动某个被调试程序(以下称debugee)的一个新的实例来进行调试,即先创建cdb,然后cdb再把你 所指定的程序创建为一个新进程进而对其调试,也允许debugee在已经运行的情况下被cdb attach上。cdb还可以对Crash Dump(程序崩溃时的内存Copy,下文将会说明)进行调试,只需要加上-z选项,后面再加上Crash Dump的文件名即可。这几种调试方式下面将会一一讲述。

3。1 调试前的准备

第 2节中对调试信息进行了理论上的说明,接下来我们来看看在实际中应该如何操作。首先我们的程序必须要经过编译,链接,并且在编译和链接时还要指定一些选项 以正确地生成调试信息。这里所使用的编译器是cl.exe,链接器是link.exe,都是微软官方的,Visual Studio就是用的这两个(CTRL+F5就是顺序调用cl和link的快捷键),如果你安装了Visual C++或Visual Studio,就会有它们,另外一种选择是安装SDK,也能够得到它们。本文所用的cl.exe和link.exe是Visual C++ 6.0的版本。若要生成调试信息,编译时我们需要加上的选项应是/Zi,而链接时则要加上/debug。在下面的调试中,我们将用C语言来写程序,所以你 有必要知道用C语言写出来的程序与用汇编写出来的有什么不同。首先,每个程序都有一个入口函数,它的地址需要在链接时指定,并被链接器放到最终可执行文件 的头部,通常用汇编语言写的程序,有选择的,你可以在源代码中指定入口函数,而用C语言写的程序则需要在链接的时候来指定入口函数,说到这你可能不以为 然,“C语言写的程序的入口函数不就是main吗?“。实际上,控制台C程序的入口函数默认情况下是C运行时的启动函数:mainCRTStartup。 然后由这个函数调用你写的main函数,所以可执行文件的头部存放的入口地址是mainCRTStartup的地址,而不是你写的main函数地址。 mainCRTStartup主要做了一些为了正确执行C/C++程序的初始化工作。它已经由微软写好了,由链接器自动链接到可执行文件中。如果你在程序 中不使用C语言的库以及一些ANSI规定的全局变量,只是单纯地使用C语言这种语法,那么你也可以不链接mainCRTStartup,直接指定你自己写 的某个函数为入口函数,这也是我们在下文中所使用的方法,具体的做法是在链接时加入如下选项:/subsystem:console /entry:你的入口函数名称。这个入口函数应该是不带参数的。现在我们来总结一下上面所讲的内容,假定你的源程序名为exam.c,你想指定的入口函 数为main,那么应该如下生成可执行程序:

C:/Pro/>cl /Zi exam.c /link /debug /subsystem:console /entry:main
另 外,就算你不链接mainCRTStartup(它会调用很多的Win32 API),也不在源程序中调用任何的系统函数。那么系统还是会把一些动态链接库,如kernel32.dll,Ntdll.dll等动态链接到你的程序所 对应的进程里,即把它们映射到你的程序对应的进程地址空间里。这是因为在你所指定的入口函数运行之前,还会有一系列的 Kernel32.dll,Ntdll.dll中的函数要运行。即在用户空间中你指定的入口函数,例如上面的main,根本不是第一个运行的函数。那么那 些函数是做什么的呢,通过大量的反汇编和调试能够推断出它们是做一些进程,线程在用户空间的初始化,设置一些异常桢等。在下面的调试中我们将会用一些手段 来研究它们。这些函数是操作系统的一部分,因些我们必须从官方网站下载它的符号文件,当然不下载也行,那么你将面临的会是一大堆的警告。说到下载,没有比 这更简单的了,你不需要预先的下载,只需要添加一个环境变量_NT_SYMBOL_PATH即可,而真正的下载工作由调试器来做,这个环境变量的值与已存 在的PATH环境变量类似,是由分号分隔的一系列的路径组成。这些路径应该包括你的调试信息文件(pdb文件)所在地,如前面的C:/Pro/。如果要下 载系统文件如Kernel32.dll,Ntdll.dll的pdb文件,你仅仅需要再加一个这样的路径:SRV*D:/Symbols*http: //msdl.microsoft.com/download/symbols,其中D:/Symbols是可更换的,你可以换成任何一个其它的路径,这 个D:/Symbls是用来存放从后面的URL路径所下载下来的系统调试信息文件的。其实你也可以预先下载系统调试信息文件到一个路径里,然后在 _NT_SYMBOL_PATH里指定那个目录,但这样一来有两个缺点,一是你必须得进行版本的匹配,做这件事简直太乏味了,二是你一次需要把整个操作系 统的调试信息文件都下载下来,可能会需要1G的空间。而通过前面设置环境变量的方式,调试器会根据需要只下载这次调试会话所需要的调试信息文件,并且它会 自动给你匹配版本。由于我们将要编写的源代码都在C:/Pro/文件夹中,生成的pdb文件也在C:/Pro/中,所以我们的 _NT_SYMBOL_PATH环境变量应该如下设置,假设你希望系统pdb文件下载到D:/Symbols:
C:/Pro/>set _NT_SYMBOL_PATH=SRV*D:/Symbols*http://msdl.microsoft.com/download/symbols;C:/Pro/
最后,我们需要在命令行中启动cdb调试器,但当前目录通常是源代码文件夹C:/Pro/,为了避免如下冗余的键入:

C:/Pro/>C:/Progs/Debug/cdb example1.exe
应该为cdb,ntsd,WinDbg设置PATH环境变量:

C:/Pro/>set PATH=%PATH%;C:/Progs/Debug/
这里的C:/Progs/Debug是Debugging Tools for Windows的安装目录。以后就可以这样来调试了:

C:/Pro/>cdb example1.exe

3。2 cdb启动新实例的调试

3。2。1 编写一源程序,启动cdb

首先我编写了下面的C程序,先用这个程序来介绍一些基本的命令,并且来验证一下调试信息中是否确切包含了上面所说的那些内容:

[example1.c]
int 		gVar;
static int sgVar;
int Inc(int Param);
static int sDec(int sParam);
void main(void)
{
int lVar;
static int slVar;
lVar = 3;
slVar = 4;
gVar = Inc(lVar);
sgVar = sDec(slVar);
}
int Inc(int Param)
{
return (Param+1);
}
int sDec(int sParam)
{
return (sParam-1);
}
对这个程序用上面所讲的方法编译链接:
C:/Pro/>cl /Zi example1.c /link /debug /subsystem:console /entry:main
接下来启动cdb调试器:

C:/Pro/>cdb example1.exe

Microsoft (R) Windows Debugger
Copyright (c) Microsoft Corporation. All rights reserved.

CommandLine: example1.exe
Symbol search path is: SRV*D:/Symbols*http://msdl.microsoft.com/download/symbols
Executable search path is:
ModLoad: 00400000 00406000 example1.exe
ModLoad: 7c920000 7c9b4000 ntdll.dll
ModLoad: 7c800000 7c91c000 C:/WINDOWS/system32/kernel32.dll
(c94.c24): Break instruction exception - code 80000003 (first chance)
eax=00251eb4 ebx=7ffd4000 ecx=00000001 edx=00000002 esi=00251f48 edi=00251eb4
eip=7c921230 esp=0012fb20 ebp=0012fc94 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
ntdll!DbgBreakPoint:
7c921230 cc int 3
0:000>
cdb 输出了此时主线程的上下文信息(这个例子中也只有这一个线程)以及程序断点信息后便会进入一个新的提示符:0:000>。以后我们会一直工作在这种 类型的提示符上,下面在这个提示符上输入一个命令来加载所有的调试信息文件,此时可能会慢一些,因为要下载系统DLL的pdb文件,所以要确保你能上网。

0:000>.reload /f

看到这个以"."号做为前缀的命令,可能你会觉得怪怪的,但实际上还有用"!"号做前缀的呢,用"."号做前缀的命令表示元命令,而用"!“号做前缀的命令表示扩展命令,这里只做一个简单的区分即可。

其 实这时我们所要调试的程序已经运行起来了,不过停在了某处,主线程处于冻结状态。这一点和Linux的Gnu调试器GDB不一样,对于GDB调试器,你先 要设置一个断点,然后再键入运行命令(如果自己不手动设置一个断点,那么程序将会一直运行直到结束,你根本没有调试的机会。),这时程序才处于运行状态。 没有运行和运行之后处于冻结状态是两个完全不同的概念。那么我们这个example1.exe停在了什么地方呢。下面我将介绍一个很重要的命令,用它我们 可以来研究这方面的问题。

3。2。2 查看堆栈及用户空间的初始化

用kb命令可以来查看堆栈,它显示栈上一些重要的信息。

0:000>kb
ChildEBP RetAddr Args to Child
0012fb1c 7c95edc0 7ffdf000 7ffd4000 00000000 ntdll!DbgBreakPoint
0012fc94 7c941639 0012fd30 7c920000 0012fce0 ntdll!LdrpInitializeProcess+0xffa
0012fd1c 7c92eac7 0012fd30 7c920000 00000000 ntdll!_LdrpInitialize+0x183
00000000 00000000 00000000 00000000 00000000 ntdll!KiUserApcDispatcher+0x7
这个命令所列出来的信息后面还要详细介绍,这里先关注一下函数的调用关系。从上面的列表可以看到有四个函数,这四个函数都是ntdll模块里的,从下至上函数依次被调用。要注意这是当前线程的用户栈里所有的东西,就四个函数,KiUserApcDispatcher是第一个,上面已经提到过,在你指定的入口函数执行之前还有很多的函数被调用,KiUserApcDispatcher是第一个被调用的,接下来它再调用_LdrpInitialize_LdrpInitialize调用LdrpInitializeProcess,再调用DbgBreakPoint。至于是谁调用的KiUserApcDispatcher,我现在只能简单的告诉你是操作系统调度例程调度的结果。深入地探讨它就离开本文的主题了。现在我们可以肯定的是程序停在了DbgBreakPoint里,因为它是栈上最后一个函数。从cdb调试器的输出可以看到example1.exe停在了DbgBreakPoint函数里的int 3语句上,int 3是一个异常,它将会通知操作系统挂起这个线程,并且通知调试器,这是操作系统对调试的一个支持。其实DbgBreakPoint函数只有一条语句,那就是int 3。敏感点的人可能会想到,这样一来,所有的程序,无论是否被调试,在运行的时候最初都会执行DbgBreakPoint函数了,这也太傻了吧?情况并非如此,当我们键入cdb example1.exe时,cdb在启动example1.exe的时候会加一个特殊的标记,在这种情况下LdrpInitializeProcess才会调用DbgBreakPoint,这又是操作系统对调试的一个支持。


本文转自
http://chenshine.blogbus.com/logs/4414354.html

posted @ 2012-03-30 20:45 RTY 阅读(800) | 评论 (0)编辑 收藏

     前面学习中,很多地方都用到了C++和JavaScript相互通信。今天就学习QtScript模块吧。

    Qt 包含完全集成的 ECMA 标准脚本引擎。Qt Script 集成了 QObject,为脚本提供了 Qt 的信号与槽 (Signals & Slots) 机制,可在 C++ 和脚本之间进行集成。 脚本支持可使开发事半功倍,QtScript提供脚本错误报告,用户可用自己的脚本跟踪程序缺陷.

   下面是一个简单的hello程序。

   

 

  1. //main.cpp  
  2. #include <QtGui/QApplication>  
  3. #include <QMessageBox>  
  4. #include <QtScript/QtScript>  
  5. #include <QPushButton>  
  6. #include "mainwindow.h"  
  7.   
  8. int main(int argc, char *argv[])  
  9. {  
  10.     Q_INIT_RESOURCE(helloscript);  
  11.     QApplication app(argc, argv);  
  12.     QScriptEngine engine;  
  13.   
  14.     //国际化  
  15.     QTranslator translator;  
  16.     translator.load("helloscript_la");  
  17.     app.installTranslator(&translator);  
  18.     engine.installTranslatorFunctions();  
  19.   
  20.     QPushButton button;  
  21.     QScriptValue scriptButton = engine.newQObject(&button);//生成C++对象的代理脚本对象  
  22.     engine.globalObject().setProperty("button", scriptButton);//将对象注册到javascript  
  23.   
  24.     //读取js文件  
  25.     QString fileName(":/helloscript.js");  
  26.     QFile scriptFile(fileName);  
  27.     scriptFile.open(QIODevice::ReadOnly);  
  28.     QTextStream stream(&scriptFile);  
  29.     QString contents = stream.readAll();  
  30.     scriptFile.close();  
  31.   
  32.     QScriptValue result = engine.evaluate(contents, fileName);//执行脚本  
  33.     if(result.isError()) {//解析js文件是否有错误  
  34.         QMessageBox::critical(0, "Hello Script",  
  35.                               QString::fromLatin1("%0:%1: %2")  
  36.                               .arg(fileName)//文件名  
  37.                               .arg(result.property("lineNumber").toInt32())//错误行号  
  38.                               .arg(result.toString()));//错误信息  
  39.         return -1;  
  40.     }  
  41.     return app.exec();  
  42. }  
  

 

 

 

 

[javascript] view plaincopy
  1. //helloscript.js  
  2. button.text = qsTr('Hello World');//note that the qTr() function is used to allow for translation  
  3. button.styleSheet = 'font-style: italic; color: #12FF12';  
  4. button.show();//调用show()槽函数  
  5. button.clicked.connect(  
  6.     function(){  
  7.        print('Hello QtScript');  
  8.     }  
  9. );  

 

 

记住还需要在.pro文件中加入:QT       += script

 

    1、QScriptEngine类为程序提供一个嵌入式脚本环境。一个应用程序中可以添加多个脚本引擎;每一个引擎都是一个轻量级自包含的虚拟机。通过调用脚本引擎的evaluate()函数可以执行脚本.

   

[c-sharp] view plaincopy
  1. QScriptEngine engine;  
  2. QScriptValue result = engine.evaluate("(3*2)-1");  
  3. qDebug() << "Result: " << result.toInt32();  

 

    

 

  

  1. QScriptEngine engine;  
  2. QScriptValue func = engine.evaluate("(function(a, b) { return a+b;})");  
  3. QScriptValueList args;  
  4. args << 1 << 2;  
  5. QScriptValue result = func.call(QScriptValue(), args);  
  6. qDebug() << "Result: " << result.toInt32();  

 

 

 

    2、QScriptValue是一个Qt Script数据类型的容器,支持ECMA-262定义的类型,如:

     原始数据类型:Undefined,Null,Boolean,Number,String,对象类型。

     另外Qt Script还内建支持QVariant,QObject和QMetaObject.

      >>对于基对象(object-based)类型(包括Date和RegExp),使用QScriptEngine对象的newT()函数(如QScriptEngine::newObject())创建一个你期望的QScriptValue类型。

      >>对于原始数据类型,直接使用QScriptValue构造函数加载。

      isT()方法能够被用来测试一个值是否是你确定的数据类型。toT()方法用来将QScriptValue转换成其他类型。当然你也可以用qscriptvalue_cast()方法.

posted @ 2012-03-29 13:43 RTY 阅读(1858) | 评论 (0)编辑 收藏

Most of us would not have expected the next major version of Mac OS X so quickly this time. But, Apple has released the developer preview-1 of OS X 10.8 Mountain Lion recently.  While people were talking about iPad 3 and iPhone 5, Mac desktop users surprised by latest OS from Apple (though it is not a final version for end users). Mac OS X 10.8 is still a developer preview version to run and test the new OS. You can directly download the official distribution of 10.8 if you have valid Apple developer ID.  Here I’m sharing few useful links to download OS X 10.8 Mountain Lion without developer login.

These files should be enough to run on normal Intel or virtual machines by using hackintosh methods.

Mountain Lion OS brings most of the features of iOS (iPad and iPhone) to desktop OS environment on top of existing Lion OS X 10.7. The major features of new OS include;

  • Messages – replaces iChat to bring full iMessage support to the Mac
  • Notification Center – just like iOS
  • Share Sheets – allows easy sharing of links, videos, photos between apps
  • AirPlay mirroring – send wireless video to an Apple TV
  • Notes
  • Reminders
  • Game Center
  • Twitter Integration
  • Gatekeeper – anti-Malware app installation guard

You can find out more information here at official link to Mountain Lion.

Hackintosh Versions of Mac OS X 10.8,

Here is the link to download developer preview –1 of OS X 10.8 Mountain Lion (you must have developer id to download form apple site)

 

How to Download Torrent and Hackintosh versions of Mac OS X 10.8 Mountain Lion

As I mentioned earlier, the official download works only with developer login. If you are trying to download though torrent sites, here is the good news.

1) Untouched version

This torrent should be working fine as per the comments on this torrent forum. I have just finished downloading this torrent, and will update you soon on how to install it on VMware or VirtualBox. This version is not modified (as mentioned ‘untouched’) to work on Hackintosh platform, but I’m hoping this will work with VMware and VirtualBox on Intel based Windows computers. I could see a comment saying he managed to install it on VMware successfully.

Download link of torrent

2) Hackintosh Version

On the same forum someone called this as Hackintosh version, but I’m not sure how it will be working.  I think this image doesn’t require installation. Just you can restore to USB stick or virtual machine hard disk, install Chameleon bootloader and boot the Hackintosh or virtual machine. If this works as said, I’m sure that will save huge time and work around. I will have a try after few days once I succeeded with above original image.

Download link of torrent

Stay tuned with Sysprobs for more Hackintosh on VMware and VirtualBox of Mac OS X 10.8 Mountain Lion news.

Recommended Posts

posted @ 2012-03-18 09:31 RTY 阅读(604) | 评论 (0)编辑 收藏

This article explains how to create a bootable (Mac) OS X 10.8 mountain Lion image (and ISO) for VMware workstation on Intel based Windows 7 computer. Recently I have mentioned about official 10.8 developer preview download and torrent download of latest OS from Apple. The original DMG file can not be booted on any hackintosh methods. But, by using this guide we can prepare a bootable image of Mountain Lion OS X and start the installation on VMware workstation as guest virtual machine.

This guide is nothing to do with Hackintosh on physical computer. I have tested on desktop virtualization software VMware workstation only. So, it will be useful to run the developer preview version of OS X 10.8 without disturbing your physical Operating Systems.  Also, it is very safe, easy and possible to use with multiple Operating Systems simultaneously.

OK, let’s come to our point. Here I’m explaining how to prepare the OS X 10.8 image and ISO which can be booted on VMware workstation with Intel based Windows computers. Usually the official dmg file should be used inside an existing Mac OS machine to install it in different partition (dual boot) or update the existing OS X. So, starting the installation on fresh virtual machine with same dmg file is not possible without doing few modifications.

This method is exactly same which we used earlier to prepare Lion OS X 10.7 bootable image. Since I already explained each steps with Lion OS X earlier, I’m not going to repeat the same instructions here. Anyhow, keep reading…..

 

What You Need?

1) A working Snow Leopard or Lion OS X virtual machine on VMware or VirtualBox.

More information available on how to install Snow Leopard on VMware, VirtualBox and Lion OS X on VMwareVirtualBox.

2) Mountain Lion DMG file (Click here to read more)

 

Summary – What We Are Going to Do?

1) We will attach a new virtual hard disk (5GB) to existing Mac OS X virtual machine.

2) Mount the Mountain Lion dmg file inside virtual machine.

3) Restore the BaseSystem and packages (from downloaded dmg file) to newly attached virtual hard disk from virtual machine. Also few modifications.

4) Now we can attach the ‘prepared’ 5GB virtual hard disk to new virtual machine to boot and start the installation.

That’s it. Its very easy. But please follow the instruction correctly.

 

Steps to Create Bootable OS X 10.8 Mountain Lion DMG on VMware Workstation

1) Attach a 5GB new virtual hard disk to working Mac OS X  virtual machine. In this example, I’m doing it with Lion OS X (10.7) VM on VMware workstation, my host is Windows 7 32 bit.

added disk

2) Start the VM. Initialize the disk and format the newly added 5GB external hard disk with following configuration.

Single partition with ‘Mac OS X Extended (Journaled)’ and ‘Apple Partition Map’ type which is available under Options in below screen.

create new partition

3) Now, we need to mount the 10.8 installation file. As you are aware OS X 10.8 installation file is in DMG format which will not work directly with VMware workstation. I tried to convert the DMG file to ISO on Windows 7 host as mentioned earlier in Sysprobs, but for some reasons it failed.

So, I have directly copied mountain Lion dmg file (using USB disk) into working Lion 10.7 virtual machine. Then mounted by double clicking the dmg file.

mounting dmg file

4) Make sure its mounted properly. Check the listed volumes as shown below.

mounted disk

Above screen shows the mounted OS X 10.8 dmg file as ‘Mac OS X Install ESD’ and my new hard disk which I formatted in Step 2 as ‘bootablelion’.

5) We are ready to start the restore and copy important packages process from mounted dmg file to new hard disk.

As I said, the further steps clearly mentioned with screen shots earlier for Lion OS X (10.7).

Please click here to visit the previous guide and follow the steps carefully.

Also, you can create Mountain Lion bootable ISO file using the same method, which is clearly mentioned by these videos ( Click here)

 

IMPORTANT NOTE:

In previous guide, the new hard disk named as ‘LionInstaller’, but in this new example it is named as ‘bootablelion’. Also, when you restore the BaseSystem image, it may overwrite the partition name and you will get a new name as ‘Mac OS X Install ESD 1’. So, either rename the partition again before continue next steps or type the new name correctly on appropriate places while typing the commands.

6) After new disk created properly, it can be attached to new virtual machine and start Mountain Lion installation. Please make sure, you have already applied VMware unlocker to be able to run Mac OS X guest virtual machines on Windows platform. Check our earlier guide on VMware 8.0 and 8.0.1 unlocker.

Here is the first screen booted by ‘prepared’ 5GB hard disk on VMware workstation 8.0.1 on Windows 7 32 bit host.

I will provide the step by step guide and additional required installation for Mountain Lion OS X 10.8 on VMware workstation in coming days.

first screen

I’m sure this guide will be helpful to prepare the bootable image of Mountain Lion for VMware workstation and VM Player. Mostly this should work with Oracle VirtualBox too, but we need to find out the correct boot loader for that. I will keep searching for that and update in this blog later.

Have fun!

Recommended Posts

posted @ 2012-03-18 09:29 RTY 阅读(2546) | 评论 (0)编辑 收藏

仅列出标题
共31页: 1 2 3 4 5 6 7 8 9 Last