下面的C代码在我的mac OS X环境中运行良好,但如果我尝试在ubuntu环境中运行此代码,每当我输入偶数个输入时,我得到一个malloc断言失败,例如“1 2” ,但奇数输入“1 2 3”有效。错误是。
a.out:malloc.c:2372:sysmalloc:断言`(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)'失败。 中止(核心倾销)
我不知道OS X和ubuntu环境之间的区别,所以如果有人能指出什么是错的我会很感激。我正在运行Ubuntu 14.04。它似乎在y!= NULL循环中崩溃
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
void free_argv(char **argv,int counter)
{
int i = 0;
for(i=0;i<counter;i++)
{
free(argv[i]);
}
free(argv);
}
int main()
{
char *line = NULL;
size_t len = 0;
ssize_t read;
char **argv = NULL;
int counter;
int status;
while ((read = getline(&line, &len, stdin)) != -1)
{
counter = 1;
printf("$ ");
char* x = strtok(line,"\n");
int i = 0;
while(x[i] != '\0')
{
if(x[i] == ' ')
{
counter++;
}
i++;
}
argv = malloc(sizeof(char*)*(counter+1));
argv[counter+1] = NULL;
i = 0;
char* y = strtok(x," ");
printf("user input:\n");
while(y != NULL)
{
argv[i] = malloc(sizeof(char)*strlen(y));
strncpy(argv[i],y,strlen(y));
printf(" %s\n",argv[i]);
y = strtok(NULL," ");
i++;
}
free_argv(argv,counter);
}
return 0;
}
答案 0 :(得分:2)
在这种情况下考虑使用valgrind - 它非常有用!它给了我什么:
==6454== Invalid write of size 8
==6454== at 0x4008CE: main (sysmalloc.c:49)
==6454== Address 0x51e0128 is 0 bytes after a block of size 40 alloc'd
==6454== at 0x4C2C27B: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==6454== by 0x4008B1: main (sysmalloc.c:47)
sysmalloc.c:49是argv[counter+1] = NULL;
- 这是行引起的问题。请注意,在C数组中索引从零开始,因此对于长度为N + 1的数组,最后一个索引是N.因此,不是写入最后argv
指针,而是将sysmalloc
内部使用的区域写入NULL造成了错误。
将此行更改为argv[counter] = NULL;
另请注意有关strcpy
用法的评论。
答案 1 :(得分:0)
除了myaut引用的argv [counter + 1]问题之外,这些行:
argv[i] = malloc(sizeof(char)*strlen(y));
strncpy(argv[i],y,strlen(y));
printf(" %s\n",argv[i]);
正在打印一个不保证以null结尾的字符串。
malloc(sizeof(char)*strlen(y));
没有为null终止符分配足够的空间(你需要strlen(y)+ 1)。 strncpy不会溢出缓冲区,但它也不会提供终结符。 printf()正在打印一个你没有终止的字符串 - 如果它打印出正确的东西,那么argv [i]缓冲区后跟一个零字节就是偶然的。
另外,我认为你不需要第一次strtok()调用,因为getline()已经为你完成了这项工作,并且argv是你变量的一个令人困惑的名字,因为它与命令行的常见用法不同输入。但是,这些都没有导致你的崩溃。