我对C编程很老了(尽管我已经多年没有用C语言编程了)但我现在完全陷入困境.我有两个源文件:
main.c中
#include#include "inputFunction.h" int main(int argc, char** argv) { char *invoiceFile=NULL, *inputFile=NULL, *configFile=NULL; getInput(argc, argv, &invoiceFile, &inputFile, &configFile); if(invoiceFile!=NULL){ free(invoiceFile); } if(inputFile!=NULL){ free(inputFile); } if(configFile!=NULL){ free(configFile); } return (EXIT_SUCCESS); }
和inputFunction.c
#include "inputFunction.h" int getInput(int argc, char** argv, char **invoiceFile, char **inputFile, char **configFile) { int i; if (argc != 3 && argc != 5 && argc != 7) { inputError(); return 1; } else { for (i = 1; i < argc; i += 2) { if (!strcmp(argv[i], "-o")) { if (*invoiceFile == NULL) { if (((*invoiceFile) = malloc((strnlen(argv[i + 1], 256) + 1) * sizeof (char))) == NULL) { perror("A problem occurred when allocating memory.\n"); return 1; } strncpy((*invoiceFile), argv[i + 1], 256); } else { inputError(); return 1; } } if (!strcmp(argv[i], "-i")) { if (*inputFile == NULL) { if (((*inputFile) = malloc((strnlen(argv[i + 1], 256) + 1) * sizeof (char))) == NULL) { perror("A problem occurred when allocating memory.\n"); return 1; } strncpy((*inputFile), argv[i + 1], 256); } else { inputError(); return 1; } } if (!strcmp(argv[i], "-c")) { if (*configFile == NULL) { if (((*configFile) = malloc((strnlen(argv[i + 1], 256) + 1) * sizeof (char))) == NULL) { perror("A problem occurred when allocating memory.\n"); return 1; } strncpy((*configFile), argv[i + 1], 256); } else { inputError(); return 1; } } } } if (*invoiceFile == NULL) { inputError(); return 1; } return 0; } void inputError() { printf("\nInvalid input\n"); printf("Correct input parameters are:\n"); printf("-o InvoiceFile\n"); printf("-i InputFile (optional)\n"); printf("-c configFile (optional)\n\n\n"); }
和头文件:
inputFunction.h
#ifndef INPUTFUNCTION_H #define INPUTFUNCTION_H #include#include #include int getInput(int argc, char** argv, char **invoiceFile, char **inputFile, char **configFile); void inputError(); #endif /* INPUTFUNCTION_H */
程序从命令行获取3个参数,每个参数后面都有一个文件名(只有一个参数必须是"-o"及其文件名).所以,当我把所有(共6个)它们运行并运行程序时,它会崩溃给我:
Project1: malloc.c:2369: sysmalloc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 * (sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long)old_end & pagemask) == 0)' failed. RUN FINISHED; Aborted; core dumped; real time: 120ms; user: 0ms; system: 0ms
所以我用valgrind给了我这个输出:
==8082== Memcheck, a memory error detector ==8082== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al. ==8082== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info ==8082== Command: ./out -i ab -c bc -o cd ==8082== ==8082== Invalid write of size 1 ==8082== at 0x4C2DAEC: strncpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==8082== by 0x400971: getInput (inputFunction.c:33) ==8082== by 0x400730: main (main.c:11) ==8082== Address 0x51fc043 is 0 bytes after a block of size 3 alloc'd ==8082== at 0x4C2A2DB: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==8082== by 0x400915: getInput (inputFunction.c:29) ==8082== by 0x400730: main (main.c:11) ==8082== valgrind: m_mallocfree.c:268 (mk_plain_bszB): Assertion 'bszB != 0' failed. valgrind: This is probably caused by your program erroneously writing past the end of a heap block and corrupting heap metadata. If you fix any invalid writes reported by Memcheck, this assertion failure will probably go away. Please try that before reporting this as a bug. ==8082== at 0x380581EF: ??? (in /usr/lib/valgrind/memcheck-amd64-linux) ==8082== by 0x38058332: ??? (in /usr/lib/valgrind/memcheck-amd64-linux) ==8082== by 0x3806257A: ??? (in /usr/lib/valgrind/memcheck-amd64-linux) ==8082== by 0x380641F3: ??? (in /usr/lib/valgrind/memcheck-amd64-linux) ==8082== by 0x3802B33C: ??? (in /usr/lib/valgrind/memcheck-amd64-linux) ==8082== by 0x3802B4C2: ??? (in /usr/lib/valgrind/memcheck-amd64-linux) ==8082== by 0x3809D58D: ??? (in /usr/lib/valgrind/memcheck-amd64-linux) ==8082== by 0x380AC14C: ??? (in /usr/lib/valgrind/memcheck-amd64-linux) sched status: running_tid=1 Thread 1: status = VgTs_Runnable ==8082== at 0x4C2A2DB: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==8082== by 0x4009F7: getInput (inputFunction.c:41) ==8082== by 0x400730: main (main.c:11)
我知道问题出在malloc中,但我找不到它.有帮助吗?我在Lubuntu 13.10上使用Netbeans 7.4和gcc 4.8.1.
部分问题可能是由于使用strnlen
和strncpy
.如果给定的输入字符串的长度strnlen
小于256,则它将返回实际长度(小于256的值).结果就是malloc
分配那么多字节.但是调用strncpy
指示缓冲区是256字节.并且strncpy
总是填充到给定长度,因此可能导致内存覆盖.
除非有使用strnlen的特定原因,否则使用strdup可能更简单,strdup将通过单个调用进行分配和复制.