GDB调试字符数组时指针和数组区别的体现

Posted Harley_Quinn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GDB调试字符数组时指针和数组区别的体现相关的知识,希望对你有一定的参考价值。

测试ftell函数时发现报错,先贴源码

// File Name: ftell.c                                                       
#include <stdio.h>
#include <stdlib.h>
 
int main(int argc, char** argv)
{
    FILE* fp = fopen("myfile.in", "r");
    if (fp == NULL) {
        perror("fopen error");
        exit(1);
    }
    char buf[4];
    fgets(buf, 4, fp);
    if (fputs(buf, fp) == EOF) {
        perror("fputs error");
        exit(1);
    }
    if (ferror(fp)) {
        perror("ferror");
        exit(1);
    }
 
    return 0;
}

错误信息如下 

于是用GDB调试,在fputs处设断点,输出字符数组

突然我想查看每个字符的值,于是看到的是这个

啊,突然想起来,buf的类型并不是char*,虽然如果作为函数输入参数的话会被当成char*,但是buf的实际类型是char (*)[4]

所以输出的是4个char (*)[4],也就是buf开始的16个字符

但是我使用p &buf[0]@sizeof(buf)会报错Only values in memory can be extended with \'@\'

想着可能需要类型转换,加了(char*)后还是报错,原来是因为只有值才能狗用@扩展,GDB会取得值的指针,然后用@往前移动

于是几个调试如下

(gdb) p buf
$1 = "lin"
(gdb) p &buf[0]
$2 = 0x7fffffffde90 "lin"
(gdb) p &buf[0]@4
Only values in memory can be extended with \'@\'.
(gdb) p (char*)&buf[0]@4
Only values in memory can be extended with \'@\'.
(gdb) p *(char*)&buf[0]@4
$3 = "lin"
(gdb) p *buf@4
$4 = "lin"

\\0是看不到的,除非单独查看那一位的字符

(gdb) p (int)buf[3]
$5 = 0
(gdb) p buf[3]
$6 = 0 \'\\000\'

OK,继续解决fputs出错的问题吧。

其实perror显示的信息很完美了,错误原因是Bad file descriptor,在这里文件描述符藏在FILE*指向的对象里,错误也就是fp。

这里我是要把信息输出到屏幕上,所以fputs的第二个输入参数应该是标准输出stdout,而不是我打开的文件指针fp。

由于fopen选择了读取模式,所以无法进行写入。

试着把fopen第二个参数改成"r+",允许写入,结果如下

该文本之前第1行是line 01,现在被改成了linlin1,因为读取3个字符时偏移量是3(即\'e\'所在位置),然后又写入了3个字符,所以"lin"替代的是"e 0"。

这里也可以发现,用"r"而不是"r+"来禁止写入能够检查出一些容易忽视的错误。

修改后如下

// File Name: ftell.c   
#include <stdio.h>
#include <stdlib.h>
  
int main(int argc, char** argv)     
{ 
    FILE* fp = fopen("myfile.in", "r");
    if (fp == NULL) {
        perror("fopen error");      
        exit(1);
    }
    char buf[4];
    fgets(buf, 4, fp);
    if (fputs(buf, stdout) == EOF) {
        perror("fputs error");      
        exit(1);
    }
    printf("\\nfile offset: %ld\\n", ftell(fp));
    if (ferror(fp)) {
        perror("ferror");
        exit(1);
    }
  
    fclose(fp);
  
    return 0;
} 
/* output:
lin
file offset: 3                                                              
*/

  

以上是关于GDB调试字符数组时指针和数组区别的体现的主要内容,如果未能解决你的问题,请参考以下文章

修改指向指针的数组中对应元素的字符出现异常,该如何解决?

从实践到原理掌握 GDB

从实践到原理掌握 GDB

从实践到原理掌握 GDB

从实践到原理掌握 GDB

字符指针操作字符数组出错,代码如问题补充,