欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C语言断点调试和编译问题总结

程序员文章站 2022-10-17 22:56:41
1. 编译环境使用vs2008,在调试过程中发现,某个函数的部分代码没有正确执行,在这部分代码处打断点调试,发现每次调试运行时总是提示断点无效。出问题的代码如下,在while(){...

1. 编译环境使用vs2008,在调试过程中发现,某个函数的部分代码没有正确执行,在这部分代码处打断点调试,发现每次调试运行时总是提示断点无效。出问题的代码如下,在while(){}代码块内部打断点提示断点无效。

[cpp]
int32 sendltemsg(void *pmsg, int32 imsglen) 

    int32 t_ileft = imsglen; 
    int32 t_iret = 0; 
    int32 t_idx = 0; 
    if((null==pmsg) || (0==imsglen)) 
    { 
        return false; 
    } 
    while(t_ileft>0) /*保证将数据全部发送出去*/ 
    { 
        t_iret = send(g_sockclientlte, &(((char*)pmsg)[t_idx]), t_ileft, 0); 
        if(t_iret == 0) 
        { 
            break; 
        } 
        else if(t_iret == socket_error) 
        { 
            int32 t_errcode = wsagetlasterror(); 
            return false; 
        } 
        t_ileft -= t_iret; 
        t_idx += t_iret; 
    }/*end of while*/ 
    return true; 

2. 那么,在什么情况下会导致运行时断点无效或不能在指定的位置打断点呢?
a) 是否编译时存在调试信息?
    需要查看编译选项,debug or release(说白了就是编译时的optimizationlevel),debug会存在调试信息。
b) 在编译完成之后代码是否有改动?
    代码可能已经和可执行文件不一致,导致打断点的位置和预期程序执行的位置不一致。如下图,断电停在a--的位置,但是程序已经输出了hello world。C语言断点调试和编译问题总结

 

c) 是否将这部分代码编译到了目标文件?
    比如条件编译的影响,没有对这部分代码进行编译,当然就不可能打断点。那么,如何判断代码是否编译到了目标文件?

3. 预处理指令#pragma
#pragma指令的作用是设定编译器的状态或者是指示编译器完成一些特定的动作。#pragma指令对每个编译器给出了一个方法,在保持与c和c++语言完全兼容的情况下,给出主机或操作专有的特征。依据定义,编译指示是机器或操作系统专有的,且对于每个编译器都是不同的。语法:#pragma para
#pragmamessage(“string”)  编译时显示一条信息
#pragmacode_seg(["section-name"[,"section-class"] ] )  设置程序中函数代码存放的代码段
#pragmawarning(…)  对warning进行处理
#pragmacomment(…)  将一个注释记录放入一个对象文件或可执行文件中
如下实例中,如果代码中不加pragma预处理指令,编译时会提示4013的warning,pragma可以禁止提示某个warning信息,并且可以设置显示编译时的消息

 C语言断点调试和编译问题总结

 

4. 在问题代码while(t_ileft>0)前后使用预编译命令#pragma message(…),发现while()语句前都进行了编译,语句后没有编译到目标文件。这是为什么?
个人认为是c编译器词法分析“贪心法”(见后面说明)导致的,我们注意到while()语句后面存在中文注释,在中文后加一个空格,编译信息出现。编译器在对代码进行编译过程中,中文字符“去”对之后的*结合,导致编译器认为while()后的注释没有结束,函数中两个注释之间的代码都被视为注释!(这可能是由于编译器对字符编码的认识不一致导致的,原因为猜想,在vc6环境下编译没有出现此问题)

 C语言断点调试和编译问题总结

 

简要说明什么是贪心法:
我们从刚学c语言就有一个疑问:怎样解释a+++b?
如果编译器的输入流截止至某个字符之前都已经被分解为一个个符号,那么下一个符号将包括从该字符之后可能组成一个符号的最长字符串。符号之间不能有空格。
比如:

[cpp] int a = 3, b; 
int *p = &a; 
b = 12/*p   /* comment */ ; 
 int a = 3, b;
 int *p = &a;
 b = 12/*p /* comment */ ;
 
b的值是几?
或者

[cpp] int *p = null; 
int i = sizeof*p; 
 int *p = null;
 int i = sizeof*p;
这种表示会是错误的吗?

大家有兴趣可以试试。

摘自 nevasun的专栏