user-0 提问: gcc环境下的月经贴：core dumped. 但确实非常奇怪，请高手给看看

回复:
user: user-1
content: 理解和讨论之前请先学会如何观察！  学会使用GDB单步调试才是楼主的当务之急！

user: user-1
content: 我不会emacs，可惜。 http://bbs.csdn.net/topics/390306165

user: user-2
content: a[n]  与  *（a+n）  是等价的，然后你照搬就能明白为什么会那样输出了

user: user-0
content: 引用 11 楼 zhao4zhong1 的回复:[quote=引用 10 楼 javashit 的回复:] [quote=引用 9 楼 zhao4zhong1 的回复:] 理解和讨论之前请先学会如何观察！  学会使用GDB单步调试才是楼主的当务之急！  我完全同意你说的 在VC环境下，通常需要Alt+8, Alt+6, Alt+5 分别打开汇编、内存、寄存器窗口 那么，在GDB下如何做呢？ [/quote] GDB常用命令 调用gdb编译需要在cc后面加 -g参数再加-o； [root@redhat home]#gdb 调试文件：启动gdb (gdb) l ：（字母l）从第一行开始列出源码 (gdb) break n :在第n行处设置断点 (gdb) break func：在函数func()的入口处设置断点 (gdb) info break： 查看断点信息 (gdb) r：运行程序 (gdb) n：单步执行 (gdb) c：继续运行 (gdb) p 变量 ：打印变量的值 (gdb) bt：查看函数堆栈 (gdb) finish：退出函数 (gdb) shell 命令行：执行shell命令行 (gdb) set args 参数:指定运行时的参数 (gdb) show args：查看设置好的参数 (gdb) show paths:查看程序运行路径；            set environment varname [=value] 设置环境变量。如：set env USER=hchen；             show environment [varname] 查看环境变量； (gdb) cd 相当于shell的cd; (gdb)pwd ：显示当前所在目录 (gdb)info program： 来查看程序的是否在运行，进程号，被暂停的原因。 (gdb)clear 行号n：清除第n行的断点 (gdb)delete 断点号n：删除第n个断点 (gdb)disable 断点号n：暂停第n个断点 (gdb)enable 断点号n：开启第n个断点 (gdb)step：单步调试如果有函数调用，则进入函数；与命令n不同，n是不进入调用的函数的 list ：简记为 l ，其作用就是列出程序的源代码，默认每次显示10行。 list 行号：将显示当前文件以“行号”为中心的前后10行代码，如：list 12 list 函数名：将显示“函数名”所在函数的源代码，如：list main list ：不带参数，将接着上一次 list 命令的，输出下边的内容。 注意 ：如果运行list 命令得到类似如下的打印，那是因为在编译程序时没有加入 -g 选项： (gdb) list 1       ../sysdeps/i386/elf/start.S: No such file or directory.         in ../sysdeps/i386/elf/start.S run：简记为 r ，其作用是运行程序，当遇到断点后，程序会在断点处停止运行，等待用户输入下一步的命令。 回车：重复上一条命令。 set args：设置运行程序时的命令行参数，如：set args 33 55 show args：显示命令行参数 continue：简讯为 c ，其作用是继续运行被断点中断的程序。 break：为程序设置断点。 break 行号：在当前文件的“行号”处设置断点，如：break  33 break 函数名：在用户定义的函数“函数名”处设置断点，如：break cb_button info breakpoints：显示当前程序的断点设置情况 disable breakpoints Num：关闭断点“Num”，使其无效，其中“Num”为 info breakpoints 中显示的对应值 enable breakpoints Num：打开断点“Num”，使其重新生效 step：简记为 s ，单步跟踪程序，当遇到函数调用时，则进入此函数体（一般只进入用户自定义函数）。 next：简记为 n，单步跟踪程序，当遇到函数调用时，也不进入此函数体；此命令同 step 的主要区别是，step 遇到用户自定义的函数，将步进到函数中去运行，而 next 则直接调用函数，不会进入到函数体内。 until：当你厌倦了在一个循环体内单步跟踪时，这个命令可以运行程序直到退出循环体。 finish： 运行程序，直到当前函数完成返回，并打印函数返回时的堆栈地址和返回值及参数值等信息。 stepi或nexti：单步跟踪一些机器指令。 print 表达式：简记为 p ，其中“表达式”可以是任何当前正在被测试程序的有效表达式，比如当前正在调试C语言的程序，那么“表达式”可以是任何C语言的有效表达式，包括数字，变量甚至是函数调用。 print a：将显示整数 a 的值 print ++a：将把 a 中的值加1,并显示出来 print name：将显示字符串 name 的值 print gdb_test(22)：将以整数22作为参数调用 gdb_test() 函数 print gdb_test(a)：将以变量 a 作为参数调用 gdb_test() 函数 bt：显示当前程序的函数调用堆栈。 display 表达式：在单步运行时将非常有用，使用display命令设置一个表达式后，它将在每次单步进行指令后，紧接着输出被设置的表达式及值。如： display a watch 表达式：设置一个监视点，一旦被监视的“表达式”的值改变，gdb将强行终止正在被调试的程序。如： watch a kill：将强行终止当前正在调试的程序 help 命令：help 命令将显示“命令”的常用帮助信息 call 函数(参数)：调用“函数”，并传递“参数”，如：call  gdb_test(55) layout：用于分割窗口，可以一边查看代码，一边测试： layout src：显示源代码窗口 layout asm：显示反汇编窗口 layout regs：显示源代码/反汇编和CPU寄存器窗口 layout split：显示源代码和反汇编窗口 Ctrl + L：刷新窗口 quit：简记为 q ，退出gdb 当然，gdb的功能远不止这些，包括多进程/多线程/信号/远程调试等功能在这里均没有提及，有需要的读者可以参考其它信息 本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/pizi0475/archive/2011/03/08/6232749.aspx 用gdb查看内存 格式: x /nfu <addr> 说明 x 是 examine 的缩写 n表示要显示的内存单元的个数 f表示显示方式, 可取如下值 x 按十六进制格式显示变量。 d 按十进制格式显示变量。 u 按十进制格式显示无符号整型。 o 按八进制格式显示变量。 t 按二进制格式显示变量。 a 按十六进制格式显示变量。 i 指令地址格式 c 按字符格式显示变量。 f 按浮点数格式显示变量。 u表示一个地址单元的长度 b表示单字节， h表示双字节， w表示四字节， g表示八字节 Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal), t(binary), f(float), a(address), i(instruction), c(char) and s(string). Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes) 举例 x/3uh buf 表示从内存地址buf读取内容， h表示以双字节为一个单位， 3表示三个单位， u表示按十六进制显示 例子： n是个局部变量 Breakpoint 1, main (argc=1, argv=0xbffff3a4) at calc.c:7 7        int n = atoi(argv[1]); (gdb) print &n $1 = (int *) 0xbffff2ec (gdb) x 0xbffff2ec 0xbffff2ec:    0x00282ff4 (gdb) print * (int *) 0xbffff2ec $2 = 2633716 (gdb) x /4xw 0xbffff2ec 0xbffff2ec:    0x00282ff4    0x080484e0    0x00000000    0xbffff378 (gdb) x /4dw 0xbffff2ec 0xbffff2ec:    2633716    134513888    0    -1073745032 (gdb) 本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/cgipro/archive/2010/12/01/6047504.aspx  比较详细的GDB用法说明http://blog.csdn.net/eroswang/article/details/2425242  gdb主要调试的是C/C++的程序。要调试C/C++的程序，首先在编译时，必须要把调试信息加到可执行文件中。使用编译器(cc/gcc/g++)的 -g 参数即可。如： [david@DAVID david]$ gcc -g hello.c -o hello [david@DAVID david]$ g++ -g hello.cpp -o hello 如果没有-g，将看不见程序的函数名和变量名，代替它们的全是运行时的内存地址。当用-g把调试信息加入，并成功编译目标代码以后，看看如何用gdb来调试。 启动gdb的方法有以下几种： 1. gdb <program> program也就是执行文件，一般在当前目录下。 2. gdb <program> core 用gdb同时调试一个运行程序和core文件，core是程序非法执行后，core dump后产生的文件。 3. gdb <program> <PID> 如果程序是一个服务程序，那么可以指定这个服务程序运行时的进程ID。gdb会自动attach上去，并调试它。program应该在PATH环境变量中搜索得到。 gdb启动时，可以加上一些gdb的启动开关，详细的开关可以用gdb -help查看。下面只列举一些比较常用的参数： -symbols <file> -s <file> 从指定文件中读取符号表。 -se file 从指定文件中读取符号表信息，并把它用在可执行文件中。 -core <file> -c <file> 调试时core dump的core文件。 -directory <directory> -d <directory> 加入一个源文件的搜索路径。默认搜索路径是环境变量中PATH所定义的路径。 [/quote]  救人救到底 送佛送到西  求emacs+gdb配置全餐文档！！！

user: user-3
content: 建议重新理一理“地址和值”

user: user-3
content: 引用char *p;   *p =  ... p是野指针，不能修改

user: user-3
content: 引用问题1：此时为何会core dump? 因为p的值是一个char‘l’， 不是一个有效地址， 属于野指针。

user: user-1
content: 引用 10 楼 javashit 的回复:[quote=引用 9 楼 zhao4zhong1 的回复:] 理解和讨论之前请先学会如何观察！  学会使用GDB单步调试才是楼主的当务之急！  我完全同意你说的 在VC环境下，通常需要Alt+8, Alt+6, Alt+5 分别打开汇编、内存、寄存器窗口 那么，在GDB下如何做呢？ [/quote] GDB常用命令 调用gdb编译需要在cc后面加 -g参数再加-o； [root@redhat home]#gdb 调试文件：启动gdb (gdb) l ：（字母l）从第一行开始列出源码 (gdb) break n :在第n行处设置断点 (gdb) break func：在函数func()的入口处设置断点 (gdb) info break： 查看断点信息 (gdb) r：运行程序 (gdb) n：单步执行 (gdb) c：继续运行 (gdb) p 变量 ：打印变量的值 (gdb) bt：查看函数堆栈 (gdb) finish：退出函数 (gdb) shell 命令行：执行shell命令行 (gdb) set args 参数:指定运行时的参数 (gdb) show args：查看设置好的参数 (gdb) show paths:查看程序运行路径；            set environment varname [=value] 设置环境变量。如：set env USER=hchen；             show environment [varname] 查看环境变量； (gdb) cd 相当于shell的cd; (gdb)pwd ：显示当前所在目录 (gdb)info program： 来查看程序的是否在运行，进程号，被暂停的原因。 (gdb)clear 行号n：清除第n行的断点 (gdb)delete 断点号n：删除第n个断点 (gdb)disable 断点号n：暂停第n个断点 (gdb)enable 断点号n：开启第n个断点 (gdb)step：单步调试如果有函数调用，则进入函数；与命令n不同，n是不进入调用的函数的 list ：简记为 l ，其作用就是列出程序的源代码，默认每次显示10行。 list 行号：将显示当前文件以“行号”为中心的前后10行代码，如：list 12 list 函数名：将显示“函数名”所在函数的源代码，如：list main list ：不带参数，将接着上一次 list 命令的，输出下边的内容。 注意 ：如果运行list 命令得到类似如下的打印，那是因为在编译程序时没有加入 -g 选项： (gdb) list 1       ../sysdeps/i386/elf/start.S: No such file or directory.         in ../sysdeps/i386/elf/start.S run：简记为 r ，其作用是运行程序，当遇到断点后，程序会在断点处停止运行，等待用户输入下一步的命令。 回车：重复上一条命令。 set args：设置运行程序时的命令行参数，如：set args 33 55 show args：显示命令行参数 continue：简讯为 c ，其作用是继续运行被断点中断的程序。 break：为程序设置断点。 break 行号：在当前文件的“行号”处设置断点，如：break  33 break 函数名：在用户定义的函数“函数名”处设置断点，如：break cb_button info breakpoints：显示当前程序的断点设置情况 disable breakpoints Num：关闭断点“Num”，使其无效，其中“Num”为 info breakpoints 中显示的对应值 enable breakpoints Num：打开断点“Num”，使其重新生效 step：简记为 s ，单步跟踪程序，当遇到函数调用时，则进入此函数体（一般只进入用户自定义函数）。 next：简记为 n，单步跟踪程序，当遇到函数调用时，也不进入此函数体；此命令同 step 的主要区别是，step 遇到用户自定义的函数，将步进到函数中去运行，而 next 则直接调用函数，不会进入到函数体内。 until：当你厌倦了在一个循环体内单步跟踪时，这个命令可以运行程序直到退出循环体。 finish： 运行程序，直到当前函数完成返回，并打印函数返回时的堆栈地址和返回值及参数值等信息。 stepi或nexti：单步跟踪一些机器指令。 print 表达式：简记为 p ，其中“表达式”可以是任何当前正在被测试程序的有效表达式，比如当前正在调试C语言的程序，那么“表达式”可以是任何C语言的有效表达式，包括数字，变量甚至是函数调用。 print a：将显示整数 a 的值 print ++a：将把 a 中的值加1,并显示出来 print name：将显示字符串 name 的值 print gdb_test(22)：将以整数22作为参数调用 gdb_test() 函数 print gdb_test(a)：将以变量 a 作为参数调用 gdb_test() 函数 bt：显示当前程序的函数调用堆栈。 display 表达式：在单步运行时将非常有用，使用display命令设置一个表达式后，它将在每次单步进行指令后，紧接着输出被设置的表达式及值。如： display a watch 表达式：设置一个监视点，一旦被监视的“表达式”的值改变，gdb将强行终止正在被调试的程序。如： watch a kill：将强行终止当前正在调试的程序 help 命令：help 命令将显示“命令”的常用帮助信息 call 函数(参数)：调用“函数”，并传递“参数”，如：call  gdb_test(55) layout：用于分割窗口，可以一边查看代码，一边测试： layout src：显示源代码窗口 layout asm：显示反汇编窗口 layout regs：显示源代码/反汇编和CPU寄存器窗口 layout split：显示源代码和反汇编窗口 Ctrl + L：刷新窗口 quit：简记为 q ，退出gdb 当然，gdb的功能远不止这些，包括多进程/多线程/信号/远程调试等功能在这里均没有提及，有需要的读者可以参考其它信息 本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/pizi0475/archive/2011/03/08/6232749.aspx 用gdb查看内存 格式: x /nfu <addr> 说明 x 是 examine 的缩写 n表示要显示的内存单元的个数 f表示显示方式, 可取如下值 x 按十六进制格式显示变量。 d 按十进制格式显示变量。 u 按十进制格式显示无符号整型。 o 按八进制格式显示变量。 t 按二进制格式显示变量。 a 按十六进制格式显示变量。 i 指令地址格式 c 按字符格式显示变量。 f 按浮点数格式显示变量。 u表示一个地址单元的长度 b表示单字节， h表示双字节， w表示四字节， g表示八字节 Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal), t(binary), f(float), a(address), i(instruction), c(char) and s(string). Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes) 举例 x/3uh buf 表示从内存地址buf读取内容， h表示以双字节为一个单位， 3表示三个单位， u表示按十六进制显示 例子： n是个局部变量 Breakpoint 1, main (argc=1, argv=0xbffff3a4) at calc.c:7 7        int n = atoi(argv[1]); (gdb) print &n $1 = (int *) 0xbffff2ec (gdb) x 0xbffff2ec 0xbffff2ec:    0x00282ff4 (gdb) print * (int *) 0xbffff2ec $2 = 2633716 (gdb) x /4xw 0xbffff2ec 0xbffff2ec:    0x00282ff4    0x080484e0    0x00000000    0xbffff378 (gdb) x /4dw 0xbffff2ec 0xbffff2ec:    2633716    134513888    0    -1073745032 (gdb) 本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/cgipro/archive/2010/12/01/6047504.aspx  比较详细的GDB用法说明http://blog.csdn.net/eroswang/article/details/2425242  gdb主要调试的是C/C++的程序。要调试C/C++的程序，首先在编译时，必须要把调试信息加到可执行文件中。使用编译器(cc/gcc/g++)的 -g 参数即可。如： [david@DAVID david]$ gcc -g hello.c -o hello [david@DAVID david]$ g++ -g hello.cpp -o hello 如果没有-g，将看不见程序的函数名和变量名，代替它们的全是运行时的内存地址。当用-g把调试信息加入，并成功编译目标代码以后，看看如何用gdb来调试。 启动gdb的方法有以下几种： 1. gdb <program> program也就是执行文件，一般在当前目录下。 2. gdb <program> core 用gdb同时调试一个运行程序和core文件，core是程序非法执行后，core dump后产生的文件。 3. gdb <program> <PID> 如果程序是一个服务程序，那么可以指定这个服务程序运行时的进程ID。gdb会自动attach上去，并调试它。program应该在PATH环境变量中搜索得到。 gdb启动时，可以加上一些gdb的启动开关，详细的开关可以用gdb -help查看。下面只列举一些比较常用的参数： -symbols <file> -s <file> 从指定文件中读取符号表。 -se file 从指定文件中读取符号表信息，并把它用在可执行文件中。 -core <file> -c <file> 调试时core dump的core文件。 -directory <directory> -d <directory> 加入一个源文件的搜索路径。默认搜索路径是环境变量中PATH所定义的路径。

user: user-0
content: 引用 9 楼 zhao4zhong1 的回复:理解和讨论之前请先学会如何观察！  学会使用GDB单步调试才是楼主的当务之急！  我完全同意你说的 在VC环境下，通常需要Alt+8, Alt+6, Alt+5 分别打开汇编、内存、寄存器窗口 那么，在GDB下如何做呢？

user: user-4
content: 跟coredump无关，就printf而言，格式说明符和提供的参数要配套，否则就是错误； 比如%s，你就得提供一个指向null结尾的char指针。

user: user-5
content: 我不太同意3楼，因为他认为每个例子的"Hello World"在常量存储区中。

user: user-5
content: /*************************************************************************     > File Name: p.c     > Author: Jukay     > Mail: hellojukay@gmail.com      > Created Time: 2014年10月21日 星期二 18时07分32秒  ************************************************************************/ #include<stdlib.h> #include<stdio.h> int main() { 	char *p；     p = (char *)malloc(sizeof (char));     *p ="Hello World"[3]; 	printf("%c\n",p); 	return 0; } 这个没问题，不过在我的机器上显示不出来，也不报错

user: user-6
content: 第一个问题是因为类型不一致. 后面的问题是p还没指向任何东西,你就上*p,能不出问题吗?  两种方案: char A; char *p = &A; *p = "hello world"[3]; ... or char *p = &"hello world"[3];

user: user-5
content: #include <stdio.h> int main() {   char *p;   *p = "hello world"[3];//悬挂指针啊   printf("%c\n", "hello"[3]);   return 0; }

user: user-7
content: 幸亏我有耐心，你还是不懂C指针啊！！！  #include <stdio.h>  int main(int argc ,char *argv[]) {   /********************************/   // (block 1) is equal to (block 2)   { // block 1     char *p = &"Hello World"[3];     printf("%s\n", p);   }    { // block 2     char const *arr = "Hello World";     char *p =  &arr[3];     printf("%s\n", p);   }   /********************************/    /********************************/   {     char const *arr = "Hello World";     char *p = arr[3]; // shit, what the f..k!     printf("%s\n", p); // coredump!   }   /********************************/    /********************************/   {     char const *arr = "Hello World";     char *p;     *p = arr[3]; // shit, is `p' a valid pointer!     printf("%s\n", p); // coredump!     printf("%c\n", *p); // coredump!   }   /********************************/    return 0;   }

user: user-5
content: 你要想引用"Helloe World"这个常量的地址，首先你就要将他保存在内存里面。 再看你的代码 #include <stdio.h> int main() { //下2行有问题，这里的"Hello World"只是一个临时存在的常量而已，只是一个字面值，这两条语句结束他的生存期就结束了。 //就像a=1一样，1 更本就不存在啊，只是a存在   char *p;   p = &"hello world"[3];   printf("%s\n", p);   return 0; }

user: user-5
content: 你看这个代码 /*************************************************************************     > File Name: p.c     > Author: Jukay     > Mail: hellojukay@gmail.com      > Created Time: 2014年10月21日 星期二 18时07分32秒  ************************************************************************/  #include<stdio.h> int main() { 	char p = "hello world"[3]; 	printf("%c\n",p); 	return 0; }