c语言 - 这个 valgrind 输出是什么意思,我怎样才能让它显示一些可以理解的东西?



我对C语言相当陌生,今天我被介绍给Valgrind。我安装它并在我的 C 计算器/方程解析器上运行它,我正在努力找出为什么我有分段错误(核心转储(,我得到了这个:

==20== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==20==  General Protection Fault
==20==    at 0x4008E27: _dl_map_object (dl-load.c:2317)
==20==    by 0x40014DD: map_doit (rtld.c:642)
==20==    by 0x4010193: _dl_catch_error (dl-error.c:187)
==20==    by 0x4002169: do_preload (rtld.c:831)
==20==    by 0x4002169: handle_ld_preload (rtld.c:929)
==20==    by 0x4004DEE: dl_main (rtld.c:1667)
==20==    by 0x40176F4: _dl_sysdep_start (dl-sysdep.c:249)
==20==    by 0x4001BB7: _dl_start_final (rtld.c:347)
==20==    by 0x4001BB7: _dl_start (rtld.c:573)
==20==    by 0x4001267: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so)
==20==    by 0x1: ???
==20==    by 0x1FFF0008AE: ???
==20==    by 0x1FFF0008BB: ???

当然,我不知道这意味着什么,我发现的关于类似错误的其他事情对我来说没有多大意义。有人可以用像我这样的人可以理解的相对简单的方式来解释这一点吗?

编辑:我尝试通过gdb运行它(@pm100建议的屁股(,只得到这个:

Program received signal SIGSEGV, Segmentation fault. 0x000000000040067b in ?? ()

编辑:由于我的代码被要求,就在这里。我可能做错了很多。

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
void write(char** dest, char* src, int index) {
int i = 0;
for (i = 0; src[i] != ''; i++) {
dest[index][i] = src[i];
}
dest[index][i] = '';
return;
}
void crite(char** dest, char src, int index) {
int i = 0;
dest[index][0] = src;
dest[index][1] = '';
return;
}
void evaluate(char* args) {
int i = 0;
int j = 0;
const char* numbers = "1234567890";
const char* operators = "+-*/";
int chunk = 0;
char** chunks = calloc(24, sizeof(char*));
char* current = calloc(24, sizeof(char));

for (i = 0; strchr("n", args[i]) == NULL; i++) {
//printf("Args[i]:%cnn", args[i]);
if (strchr(numbers, args[i]) != NULL) {
//printf("Number added to current: %cnn", args[i]);
current[j] = args[i];
//printf("nCurrent: %sn", current);
j++;
} else if (strchr(operators, args[i]) != NULL) {
write(chunks, current, chunk);
chunk++;
crite(chunks, args[i], chunk);
chunk++;
j = 0;
free(current);
current = calloc(24, sizeof(char));
//printf("Terminated with operator and operator added.nn");
} else {
printf("ERROR: Encountered invalid token.nn");
return;
}
}
for (i = 0; chunks[i] != NULL; i++) 
//printf("n-Chunk: %snn", chunks[chunk]);
return;
}
int main(int argc, char** argv) {
evaluate(argv[1]);
}

我用来编译它的命令是gcc calculator.c -g -o calculator

示例命令:./calculator 1*2

更新:Valgrind的问题是由我使用的Windows子系统引起的,所以只要你在linux上运行Valgrind,它应该没问题。我在 VM 中尝试过它,它起作用了。

另外,感谢您帮助我修复我的分段错误,即使这不是问题的最初内容:(

在 valgrind 下运行此代码,结果如下:

[dbush@db-centos ~]$ valgrind /tmp/x1 1*2
==1431== Memcheck, a memory error detector
==1431== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==1431== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==1431== Command: /tmp/x1 1*2
==1431== 
==1431== Invalid write of size 1
==1431==    at 0x80484B3: write (x1.c:8)
==1431==    by 0x80485E8: evaluate (x1.c:39)
==1431==    by 0x804869D: main (x1.c:61)
==1431==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==1431== 
==1431== 
==1431== Process terminating with default action of signal 11 (SIGSEGV)
==1431==  Access not within mapped region at address 0x0
==1431==    at 0x80484B3: write (x1.c:8)
==1431==    by 0x80485E8: evaluate (x1.c:39)
==1431==    by 0x804869D: main (x1.c:61)
==1431==  If you believe this happened as a result of a stack
==1431==  overflow in your program's main thread (unlikely but
==1431==  possible), you can try to increase the size of the
==1431==  main thread stack using the --main-stacksize= flag.
==1431==  The main thread stack size used in this run was 10485760.
==1431== 
==1431== HEAP SUMMARY:
==1431==     in use at exit: 120 bytes in 2 blocks
==1431==   total heap usage: 2 allocs, 0 frees, 120 bytes allocated
==1431== 
==1431== LEAK SUMMARY:
==1431==    definitely lost: 0 bytes in 0 blocks
==1431==    indirectly lost: 0 bytes in 0 blocks
==1431==      possibly lost: 0 bytes in 0 blocks
==1431==    still reachable: 120 bytes in 2 blocks
==1431==         suppressed: 0 bytes in 0 blocks
==1431== Rerun with --leak-check=full to see details of leaked memory
==1431== 
==1431== For counts of detected and suppressed errors, rerun with: -v
==1431== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 13 from 8)

所以在write的这一行:

dest[index][i] = src[i];

您正在取消引用 NULL 指针并尝试在其中写入。 有问题的 NULL 指针是dest[index],这是 NULL,因为您使用calloc来分配内存。 以下是您所做的操作:

char** chunks = calloc(24, sizeof(char*));
char* current = calloc(24, sizeof(char));

您将chunks创建为指针数组,但未为这些指针分配任何内容。 您需要遍历每个数组元素并为每个元素分配空间:

char** chunks = calloc(24, sizeof(char*));
for (i=0; i<24; i++) {
chunks[i] = calloc(24, sizeof(char));
}

或者,您可以在复制之前以writecrite方式分配此内存:

void write(char** dest, char* src, int index) {
int i = 0;
dest[index] = calloc(24, sizeof(char));
for (i = 0; src[i] != ''; i++) {
dest[index][i] = src[i];
}
dest[index][i] = '';
return;
}
void crite(char** dest, char src, int index) {
int i = 0;
dest[index] = calloc(2, sizeof(char));
dest[index][0] = src;
dest[index][1] = '';
return;
}

这是来自 Linux 加载程序深处的堆栈跟踪。Valgrind 创建一个沙箱执行环境并将您的程序加载到其中,其中的各种工具可以将自己的检测代码插入您的指令流中。

这是奇特的东西:非常依赖于良好的valgrind构建,并注意正确构建测试中的程序。仅靠这个微小的堆栈跟踪无法解释出了什么问题。装载机在尝试加载瓦尔格林德时可能会死亡。或者,当它试图加载您的程序时,它可能在沙箱中消亡。问题可能出在 valgrind 二进制文件或程序的二进制文件中,从而导致 Linux 加载程序失败。甚至有可能(我不知道(valgrind 包含自己的加载器副本,并且该副本构建不正确,因此正在消亡。

更大的图景是,valgrind 不是一个好的工具,可以在您的(我希望(小程序中调试一个简单的 seg 错误。 更有可能取得成果的两件事是正确构建和运行程序,以便gdb生成正确的符号堆栈跟踪,并简单地插入fprintf

这应该使用 gdb 生成堆栈跟踪:

$ gcc calculator.c -g -o calculator
$ gdb ./calculator
(gdb) run

如果你需要命令行参数来触发错误,你可以给它们set args,例如

(gdb) set args 1*2
(gdb) run

如果您没有看到堆栈跟踪,那么您的构建环境几乎可以肯定已损坏:您的编译器或 gdb 有问题。

另一种技术不是很优雅,但仍然有效,是从main()的第一行开始添加fprintf(stderr, ...),然后定期添加。最后一个输出告诉您执行过程有多远。当你是一个初级程序员时,在你熟悉语言、编译器和编写-编译-调试-修改周期之前,避免学习新工具会更有效率。

当我运行您的程序时,我收到 gdb 关于第 8 行的投诉(我的剪切和粘贴不起作用(

您的工具链似乎存在一些问题

您甚至可以编写和运行hello world程序吗?

#include <stdio.h>
int main()
{
printf("hello worldn");
}

相关内容

  • 没有找到相关文章

最新更新