- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我正在构建的内核模块中的一些结构存在一个小问题,所以我认为如果有一种简单的方法来打印结构及其值会很好——下面是一个小的用户态示例我的意思。
假设我们有如下简单的 C 示例(以 bash 命令的形式给出):
FN=mtest
cat > $FN.c <<EOF
#include <stdio.h> //printf
#include <stdlib.h> //calloc
struct person
{
int age;
int height;
};
static struct person *johndoe;
main ()
{
johndoe = (struct person *)calloc(1, sizeof(struct person));
johndoe->age = 6;
asm("int3"); //breakpoint for gdb
printf("Hello World - age: %d\n", johndoe->age);
free(johndoe);
}
EOF
gcc -g -O0 $FN.c -o $FN
# just a run command for gdb
cat > ./gdbcmds <<EOF
run
EOF
gdb --command=./gdbcmds ./$FN
如果我们运行这个例子,程序会编译,gdb 会运行它,并在断点处自动停止。在这里我们可以做以下事情:
Program received signal SIGTRAP, Trace/breakpoint trap.
main () at mtest.c:20
20 printf("Hello World - age: %d\n", johndoe->age);
(gdb) p johndoe
$1 = (struct person *) 0x804b008
(gdb) p (struct person)*0x804b008
$2 = {age = 6, height = 0}
(gdb) c
Continuing.
Hello World - age: 6
Program exited with code 0300.
(gdb) q
如图所示,在 gdb 中我们可以将结构指针 johndoe
的值打印(转储?)为 {age = 6, height = 0}
... I想做同样的事情,但直接来自 C 程序;如以下示例所示:
#include <stdio.h> //printf
#include <stdlib.h> //calloc
#include <whatever.h> //for imaginary printout_struct
struct person
{
int age;
int height;
};
static struct person *johndoe;
static char report[255];
main ()
{
johndoe = (struct person *)calloc(1, sizeof(struct person));
johndoe->age = 6;
printout_struct(johndoe, report); //imaginary command
printf("Hello World - age: %d\nreport: %s", johndoe->age, report);
free(johndoe);
}
这将产生如下输出:
Hello World - age: 6
$2 = {age = 6, height = 0}
所以我的问题是 - 是否存在像虚构的 printout_struct
这样的函数 - 或者是否有另一种方法可以实现这样的打印输出?
在此先感谢您的帮助,
干杯!
最佳答案
只是想说 - 感谢您提供的所有出色且快速的答案,帮助我理解了问题(为什么 C 中没有这样的“ native ”函数)!
(很抱歉回答我自己的问题 - 这样做是为了不混淆原始帖子,并且能够格式化代码)
在进一步寻找的过程中,我设法找到了:
这说明了使用进程本身的 pid 调用 gdb
的技巧,因此我修改了在那里找到的 dumpstack
函数,以获得以下代码:
FN=mtest
cat > $FN.c <<EOF
#include <stdio.h> //printf
#include <stdlib.h> //calloc, system
extern const char *__progname;
struct person
{
int age;
int height;
};
static struct person *johndoe;
static char report[255];
static void printout_struct(void* invar, char* structname){
/* dumpstack(void) Got this routine from http://www.whitefang.com/unix/faq_toc.html
** Section 6.5. Modified to redirect to file to prevent clutter
*/
/* This needs to be changed... */
char dbx[160];
sprintf(dbx, "echo 'p (struct %s)*%p\n' > gdbcmds", structname, invar );
system(dbx);
sprintf(dbx, "echo 'where\ndetach' | gdb -batch --command=gdbcmds %s %d > struct.dump", __progname, getpid() );
system(dbx);
sprintf(dbx, "cat struct.dump");
system(dbx);
return;
}
main ()
{
johndoe = (struct person *)calloc(1, sizeof(struct person));
johndoe->age = 6;
printout_struct(johndoe, "person");
johndoe->age = 8;
printout_struct(johndoe, "person");
printf("Hello World - age: %d\n:", johndoe->age);
free(johndoe);
}
EOF
gcc -g -O0 $FN.c -o $FN
./$FN
基本上最终显示了我想要的内容:
0x00740422 in __kernel_vsyscall ()
$1 = {age = 6, height = 0}
0x00740422 in __kernel_vsyscall ()
$1 = {age = 8, height = 0}
Hello World - age: 8
不过,我不确定它是否适用于内核模块......
再次感谢您的帮助,
干杯!
编辑:我认为它不适用于内核模块的原因是,在这种情况下,我们有一个带有进程 ID 的用户态程序;我们只需从这个程序中调用 gdb
,同时向它指示我们的 PID - 这样 gdb
就可以“附加”到我们的进程;然后,由于还指示 gdb
加载带有调试符号的可执行文件(因此它将“知道”结构是什么),并指示给定结构变量所在的地址, gdb
然后可以打印出结构。
对于内核模块——首先,我不认为它们是具有唯一 PID 的“进程”,因此 gdb
将没有任何附加对象!事实上,有一个内核调试器,kgdb它实际上可以闯入正在运行的内核并单步执行模块源代码;但是,您需要通过串行连接连接第二台机器 - 或者虚拟机,请参阅 Linux Hacks: Setting up kgdb using kvm/qemu .
因此,无论如何,gdb
似乎无法检查当前正在运行的主机内核的内存 gdb
正在运行 - 但我会尝试进行实验,如果实验结果并非如此,我一定会发布 :)
关于c - Linux C : Easy & 'pretty' dump/printout of structs (like in gdb) - from source code?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3311182/
这些指针之间有区别吗?每次通话到底发生了什么。 *p++ (*p)++, *(p)++ 最佳答案 1和3是一样的。 请记住 ++ 的后缀和一元形式。和 --有一个结果和一个副作用: x++ 的结果是
这个问题已经有答案了: difference between grep Vs cat and grep (5 个回答) 已关闭 8 年前。 我看到一个例子,其中有人这样做: cat source.tx
它曾经有效。现在,当我添加一个断点时: saveSnippet: (title, imageUrl, role) => { debugger; ... chrome (
开发.Net Web应用程序时,如果生成运行时错误,则会显示一些在Exception类中找不到的“额外”调试信息。 它显示了“源错误”部分,其中显示了代码摘录,其中行号准确显示了错误的产生位置,并显示
Firefox 中的“源”和“生成的源”有什么区别? 请举例说明。 编辑: 7 月 3 日 “搜索引擎”使用哪个来源,生成的还是生成前的? 最佳答案 Source 将显示页面加载的源(由服务器提供)。
对于具有两个不同工作表的Excel文件,我有两个OLE DB源。工作表A和工作表B。工作表A单元格I6包含日期,我想组合这两个源并在工作表B中添加一列,以将该值设置为工作表A的日期值。有可能做到吗?任
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
这是我的代码: import speech_recognition as sr r = sr.Recognizer() with sr.Microphone() as source: prin
我是 mysql 新手。我正在尝试 setter 工示例数据库 我尝试了 stackoverflow 中提到的一些方法,但没有帮助 谁能告诉我如何解决这个问题 SELECT 'LOADING depa
在终端中,我启动程序如下: 1) source env.sh 2) source activate enviroment 3) program --args 除了在 Pycharm 中并调试代码之外,
IntelliJ 如何知道目录是“源”还是“测试源”?如何始终将目录标记为“测试源”? build.gradle 1 apply plugin: 'java' apply plugin: 'idea'
这个问题类似于Source script to separate environment in R, not the global environment , 但有一个关键的转折。 考虑一个源另一个脚
和有什么区别--devtool source-map & eval-source-map ? 最佳答案 webpack 文档有一个方便的图表,说明这些不同的选项可能适合哪些情况。 他们显示eval-s
这个问题已经有答案了: Issue with virtualenv - cannot activate (36 个回答) 已关闭 4 年前。 venv) C:\Users\Sunil\PycharmP
在以前版本的 Akka Streams 中,groupBy 返回一个 Source 的 Source 可以具体化为一个 Source[Seq [A]]. 在 Akka Streams 2.4 中,我看
这个问题已经有答案了: Issue with virtualenv - cannot activate (36 个回答) 已关闭 4 年前。 venv) C:\Users\Sunil\PycharmP
是否可以获取 Bash 片段的源代码,但仅在特定条件成立时才实际提供其中的函数? 所以我要问的是,我可以无条件地获取目录中的所有文件,但获取的文件包含是否向采购外壳提供功能的逻辑。 例子: .bash
我无法查看 JavaCore.class 源代码,但我可以很好地使用代码。 例如,要查看方法JavaCore.create(..) 的源代码,我ctrl - click(或按f3) 在 JavaCor
-- Sample employee database -- See changelog table for details -- Copyright (C) 2007,2008, MySQL
当我在我的 IDE 中编译项目时它工作正常但是当我在 bamboo 中编译时它给我以下错误。 我已经检查过我在任务中配置的 jdk 版本是 1.6,我还尝试从 pom 中的 maven 插件强制执行
我是一名优秀的程序员,十分优秀!