我一直在学习Zed Shaw的Learn C The Hard Way,我已经完成了练习20,可以在这里查看:http://c.learncodethehardway.org/book/ex20.html。我在VirtualBox上使用Linux Mint KDE,我用gedit编写代码,用Kate编写makefile(出于语法原因——我在gedit中一直有错误)。
在编译代码时出现一些错误后,我只是直接复制并粘贴它,看看我是否只是没有正确地键入它,但我仍然使用Valgrind输出以下错误:
valgrind make ex20
==2715== Memcheck, a memory error detector
==2715== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==2715== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==2715== Command: make ex20
==2715==
cc -Wall -g -DNDEBUG ex20.c -o ex20
In file included from ex20.c:1:0:
dbg.h:1:0: error: unterminated #ifndef
#ifndef __dbg_h__
^
ex20.c: In function ‘test_debug’:
ex20.c:9:5: warning: implicit declaration of function ‘debug’ [-Wimplicit-function-declaration]
debug("I have Brown Hair.");
^
ex20.c: In function ‘test_log_err’:
ex20.c:17:5: warning: implicit declaration of function ‘log_err’ [-Wimplicit-function-declaration]
log_err("I believe everything is broken.");
^
ex20.c: In function ‘test_log_warn’:
ex20.c:23:5: warning: implicit declaration of function ‘log_warn’ [-Wimplicit-function-declaration]
log_warn("You can safely ignore this.");
^
ex20.c: In function ‘test_log_info’:
ex20.c:29:5: warning: implicit declaration of function ‘log_info’ [-Wimplicit-function-declaration]
log_info("Well I did something mundane.");
^
ex20.c: In function ‘test_check’:
ex20.c:39:5: warning: implicit declaration of function ‘check_mem’ [-Wimplicit-function-declaration]
check_mem(block); // should work
^
ex20.c:42:5: warning: implicit declaration of function ‘check’ [-Wimplicit-function-declaration]
check(input, "Failed to open %s.", file_name);
^
ex20.c:48:1: warning: label ‘error’ defined but not used [-Wunused-label]
error:
^
ex20.c: In function ‘test_sentinel’:
ex20.c:64:13: warning: implicit declaration of function ‘sentinel’ [-Wimplicit-function-declaration]
sentinel("I shouldn't run.");
^
ex20.c:70:1: warning: label ‘error’ defined but not used [-Wunused-label]
error:
^
ex20.c: In function ‘test_check_mem’:
ex20.c:83:1: warning: label ‘error’ defined but not used [-Wunused-label]
error:
^
ex20.c: In function ‘test_check_debug’:
ex20.c:90:5: warning: implicit declaration of function ‘check_debug’ [-Wimplicit-function-declaration]
check_debug(i != 0, "Oops, I was 0.");
^
ex20.c:93:1: warning: label ‘error’ defined but not used [-Wunused-label]
error:
^
ex20.c: In function ‘main’:
ex20.c:115:1: warning: label ‘error’ defined but not used [-Wunused-label]
error:
^
make: *** [ex20] Error 1
==2715==
==2715== HEAP SUMMARY:
==2715== in use at exit: 79,052 bytes in 1,433 blocks
==2715== total heap usage: 3,370 allocs, 1,937 frees, 205,837 bytes allocated
==2715==
==2715== LEAK SUMMARY:
==2715== definitely lost: 0 bytes in 0 blocks
==2715== indirectly lost: 0 bytes in 0 blocks
==2715== possibly lost: 0 bytes in 0 blocks
==2715== still reachable: 79,052 bytes in 1,433 blocks
==2715== suppressed: 0 bytes in 0 blocks
==2715== Rerun with --leak-check=full to see details of leaked memory
==2715==
==2715== For counts of detected and suppressed errors, rerun with: -v
==2715== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
根据他制作的输出,我决定Makefile应该如下:
CFLAGS=-Wall -g -DNDEBUG
all: ex20
clean:
rm -f ex20
如果有人能解释我得到的错误的原因(除了定义隐式定义的函数是什么——我知道),以及如何避免类似的错误,我将不胜感激。非常感谢。
在以#ifndef
(dbg.h
)开头的文件末尾添加#endif
。
ex20.c:64:13: warning: implicit declaration of function ‘sentinel’ [-Wimplicit-function-declaration]
sentinel("I shouldn't run.");
要解决这种错误,您应该在.c文件的顶部或.h文件中添加函数的原型。参见功能原型
ex20.c:93:1: warning: label ‘error’ defined but not used [-Wunused-label]
error:
很明显,您定义了一个标签error:
,但没有使用它。
正如评论中所提到的,首先,您不需要在valgrind中运行make,除非您正在调试/测试make本身,所以要构建您的程序,您可以这样做:
make ex20
然后你可以运行它:
./ex20
或者在valgrind下运行:
valgrind ./ex20
如果你想的话,你可以在makefile中添加一条规则来为你运行:
CFLAGS=-Wall -g -DNDEBUG
all: ex20
run: ex20
./ex20
grind: ex20
valgrind ./ex20
clean:
rm -f ex20
请注意,这并不包括实际构建ex20的配方——尽管也没有显示在你的问题中
其次,我们仍然可以看到编译器的错误。修复编译器错误和警告的主要规则是从顶部开始,这里的第一个错误是
In file included from ex20.c:1:0:
dbg.h:1:0: error: unterminated #ifndef
#ifndef __dbg_h__
这实际上是很有信息的。我们可以看到,dbg.h使用include保护来防止同一个头被单个.c文件多次包含,但看起来并没有终止#endif
。典型的结构如
#ifndef __headername_h
#define __headername_h
//Lots of header content
#endif
您可能可以通过在文件末尾添加#endif来解决此问题,但也有可能是某些内容进一步不同步。但是,如果头文件没有以#endif结尾,那几乎可以肯定是问题所在。
修复该问题,然后重新编译。你可能会发现其他警告/错误消失了——谁知道第一个错误的影响是什么。如果没有弄清楚函数在哪个头文件中,并将其包括在内。
未使用的标签也可能是第一个错误的副作用。代码中的:error标签由调试宏使用。