这比我以前的Valgrind问题更有针对性;我正在尝试在解析命令行选项时缩小写入和读取错误:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/utsname.h>
#include <sys/stat.h>
#include <string.h>
#include <locale.h>
#include <bzlib.h>
#include <zlib.h>
#include "starch.h"
#define BUFMAXLEN 1024
int main(int argc, char **argv) {
if (parseCommandLineInputs( &argc, &argv ) != 0)
exit(EXIT_FAILURE);
return 0;
}
int parseCommandLineInputs(int *argc, char ***argv) {
pid_t pid;
struct utsname uts;
char uniqTag[BUFMAXLEN];
if ((*argc == 1) || (*argc > 4)) {
printUsage();
return -1;
}
if ((pid = getpid()) < 0) {
fprintf(stderr, "\n\t[starch] - Error: Could not obtain process ID\n\n");
return -1;
}
uname( &uts );
sprintf(uniqTag, "pid%d.%s", pid, uts.nodename);
switch (*argc) {
case 2: {
if (strcmp(*argv[1], "-") != 0) {
if (fileExists(*argv[1]) != 0) { /* standard input */
...
}
return 0;
}
int fileExists(char *fn) {
struct stat buf;
int i = stat (fn, &buf);
if (i == 0)
return 0;
return -1;
}
void printUsage() {
fprintf(stderr, "my usage statement\n\n");
}
我的makefile如下:
CC = gcc
CFLAGS = -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE=1 -DUSE_ZLIB -O3 -Wformat -Wall -pedantic -std=gnu99 -g
BIN = ../bin
all: starch
rm -rf *~
starch: starch.o
mkdir -p $(BIN) && $(CC) ${CFLAGS} starch.o -lbz2 -lz -o ${BIN}/starch
rm -rf *~
clean:
rm -rf *.o *~ ${BIN}/starch
当我使用valgrind
运行时出现以下错误:
$ valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=20 --track-fds=yes -v ../bin/starch
...
==2675== 1 errors in context 1 of 2:
==2675== Invalid read of size 8
==2675== at 0x3AB4262243: fwrite (in /lib64/libc-2.5.so)
==2675== Address 0x7fedffd68 is on thread 1's stack
==2675==
==2675==
==2675== 1 errors in context 2 of 2:
==2675== Invalid write of size 8
==2675== at 0x401AA6: parseCommandLineInputs (starch.c:217)
==2675== by 0x7FF0000AF: ???
==2675== by 0x401DFA: main (starch.c:46)
==2675== Address 0x7fedffd68 is on thread 1's stack
第一个错误并没有告诉我任何我可以使用的错误,因为我没有在任何地方使用fwrite()
。
第二个错误在fprintf
的{{1}}语句中被触发。
第46行是以下行:
printUsage()
第217行是以下行:
if (parseCommandLineInputs( &argc, &argv ) != 0)
我的应用程序有什么问题可以解释为什么会出现这些错误?
答案 0 :(得分:4)
马上突然出现两件事:
* argv [1]与(* argv)[1]不同,这可能是你的意思。数组下标优先于指针解除引用。这会导致指针无效。正如许多有经验的程序员会告诉你的那样:“不要试图记住操作员的优先顺序 - 如果有疑问则使用括号,如果不是仅仅使用它们”。
-O3在调试时是一个很大的NO-NO。编译器会破坏你的代码,使你的生活变得不可能。变量可以完全消失,函数可以在内联时神秘地消失。如果你的代码编译,链接和运行-O0(IIRC包含内联汇编的一些代码需要-O1和一些(所有?)GCC版本)使用它,否则最多使用-O1。
答案 1 :(得分:0)
缺少太多,所以不容易说出发生了什么。我认为pid
是pid_t
?
我接下来唯一看到的就是这个:
sprintf(uniqTag, "pid%d.%s", pid, uts.nodename);
pid_t
不一定是int
,因此sprintf
在解析其参数并弄乱堆栈时可能在错误的轨道上。但gcc
应该告诉你是否使用-Wall
进行编译,我认为。
尝试使用不同的编译器进行编译,例如