我有一个函数来解析文件并计算一些东西。功能如下:
int meta_counter(FILE *meta_file){
int counter = 0;
char *c;
char line[1024];
while ((c = fgets(line, sizeof(line), meta_file)) != NULL)
{
char *first = malloc(sizeof(c));
strcpy(first,c);
char *rest = strchr(first, ' ');
*rest = 0;
if (strcmp(first,"Start") != 0 && strcmp(first,"End") != 0) {
//handle typos
char *d = remove_white_spaces(c);
replace_string(d,';',':');
replace_string(d,'.',':');
char *e = (char*)malloc(sizeof(d) + 1);
remove_string(e, d, ' ');
// put a ':' at the end of the line
if (e[strlen(e)-1] != ':') e[strlen(e)] = ':';
//count operators in line 'e'
char *key = ":";
char *ptr = e;
while((ptr = strchr(ptr, ':')) != NULL) {
counter++;
ptr++;
}
}
}
rewind(meta_file);
return counter;
}
当我在Mac OSX上编译并运行这个程序时,一切都很顺利。但是当我编译(编译没有问题)并在Linux上运行时,它给了我这样的错误:
*** Error in `./sim01': malloc(): memory corruption: 0x0000000001bc7170 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x77725)[0x7f4cf974a725]
/lib/x86_64-linux-gnu/libc.so.6(+0x819be)[0x7f4cf97549be]
/lib/x86_64-linux-gnu/libc.so.6(__libc_malloc+0x54)[0x7f4cf97565a4]
./sim01[0x4013d7]
./sim01[0x401f8b]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f4cf96f3830]
./sim01[0x400a99]
======= Memory map: ========
00400000-00403000 r-xp 00000000 08:05 3145767 /home/pregis/workspace/cpp-mars/Sim01/sim01
00602000-00603000 r--p 00002000 08:05 3145767 /home/pregis/workspace/cpp-mars/Sim01/sim01
00603000-00604000 rw-p 00003000 08:05 3145767 /home/pregis/workspace/cpp-mars/Sim01/sim01
01bc6000-01be7000 rw-p 00000000 00:00 0 [heap]
7f4cf4000000-7f4cf4021000 rw-p 00000000 00:00 0
7f4cf4021000-7f4cf8000000 ---p 00000000 00:00 0
7f4cf94bd000-7f4cf94d3000 r-xp 00000000 08:05 25559117 /lib/x86_64-linux-gnu/libgcc_s.so.1
7f4cf94d3000-7f4cf96d2000 ---p 00016000 08:05 25559117 /lib/x86_64-linux-gnu/libgcc_s.so.1
7f4cf96d2000-7f4cf96d3000 rw-p 00015000 08:05 25559117 /lib/x86_64-linux-gnu/libgcc_s.so.1
7f4cf96d3000-7f4cf9893000 r-xp 00000000 08:05 25559903 /lib/x86_64-linux-gnu/libc-2.23.so
7f4cf9893000-7f4cf9a92000 ---p 001c0000 08:05 25559903 /lib/x86_64-linux-gnu/libc-2.23.so
7f4cf9a92000-7f4cf9a96000 r--p 001bf000 08:05 25559903 /lib/x86_64-linux-gnu/libc-2.23.so
7f4cf9a96000-7f4cf9a98000 rw-p 001c3000 08:05 25559903 /lib/x86_64-linux-gnu/libc-2.23.so
7f4cf9a98000-7f4cf9a9c000 rw-p 00000000 00:00 0
7f4cf9a9c000-7f4cf9ac2000 r-xp 00000000 08:05 25559843 /lib/x86_64-linux-gnu/ld-2.23.so
7f4cf9c91000-7f4cf9c94000 rw-p 00000000 00:00 0
7f4cf9cbe000-7f4cf9cc1000 rw-p 00000000 00:00 0
7f4cf9cc1000-7f4cf9cc2000 r--p 00025000 08:05 25559843 /lib/x86_64-linux-gnu/ld-2.23.so
7f4cf9cc2000-7f4cf9cc3000 rw-p 00026000 08:05 25559843 /lib/x86_64-linux-gnu/ld-2.23.so
7f4cf9cc3000-7f4cf9cc4000 rw-p 00000000 00:00 0
7ffcdc988000-7ffcdc9a9000 rw-p 00000000 00:00 0 [stack]
7ffcdc9c6000-7ffcdc9c8000 r--p 00000000 00:00 0 [vvar]
7ffcdc9c8000-7ffcdc9ca000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
Aborted (core dumped)
我发现错误在这一行:char *first = malloc(sizeof(c));
。我试图增加malloc函数内部的数量(比如乘以1000,以确保它可以处理它),看看while循环是否运行不止一次(它在第二次运行时崩溃),但它只运行另一次(现在在3次运行时崩溃)迭代(应该运行几次)。
我想在两个编译器上一定有不同的地方,所以这里是我的gcc版本:
Mac OSX:$ gcc -v
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 8.0.0 (clang-800.0.38)
Target: x86_64-apple-darwin15.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
Linux (Ubuntu): $ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 5.4.0-6ubuntu1~16.04.2' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-5 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.2)
任何想法?
当你说sizeof(c)
时,我确信你希望它返回字符串的大小。它实际做的是sizeof(char*)
,通常在64位平台上是8字节。然后将整行复制到其中,这会导致未定义的行为。
接下来对同样只有8个字节的sizeof(d)
做同样的操作。
对于sizeof(line)
,这是非常不同的,因为line
是char[1024]
,它的大小是已知的。
您可以通过使用strdup()
来简化整个代码,它将一次完成分配和复制。
我在那里看不到任何free()
调用,这会导致内存泄漏。尤其是在循环中。
请学习如何使用调试器,它会立即显示您分配的内存量不足。并学习如何释放已分配的内存。
在char *first = malloc(sizeof(c));
行中,sizeof(c)
不返回字符串的大小,而是c
指针的大小:8,因为您在64位机器上。
您应该尝试使用:char *first = malloc(sizeof(strlen(c) + 1));
来分配正确的大小。
另一个解决方案是使用strdup
函数:
/* alloctate memory to store string and copy the data*/
char *first = strdup(c);
警告: Their is no trace of free()
is your code.
sizeof(c)
是指向char类型的指针的大小。
您可以使用sizeof(line)
代替。Line是一个数组,sizeof的作用与数组不同,它给出了数组中所有元素的总大小。
另一种选择是使用malloc(strlen(c)+1)