尝试执行“/bin/ls -l /usr/include”时出现奇怪的错误
Strange errors appearing when trying to execute "/bin/ls -l /usr/include"
所以我正在尝试进行 shell 实施,它似乎工作得很好。除了一个非常奇怪的问题。输入命令“/bin/ls -l /usr/include”后出现这些错误:
错误 1:
a.out: malloc.c:2379: sysmalloc: Assertion `(old_top == initial_top
(av) && old_size == 0) || ((unsigned long) (old_size) >= MINSIZE &&
prev_inuse (old_top) && ((unsigned long) old_end & (pagesize - 1)) ==
0)' failed. Aborted (core dumped)
错误 2:
realloc(): invalid pointer Aborted (core dumped)
我的代码:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
char **parse_cmdline( const char *cmdline )
{
int token_count = 1;
for(int i = 0; cmdline[i] != '[=12=]';i++)
{
if(cmdline[i] == ' ')
{
token_count++;
}
}
char *token = strtok((char*)cmdline, " ");
char **arr = malloc(token_count+1);
int i;
for(i = 0;token != NULL;i++)
{
arr[i] = token;
token = strtok(NULL, " ");
}
arr[i] = NULL; // make last element NULL for execvp() to work properly
return arr;
}
int main(void)
{
int fd = 0; // set read() to read from STDIN_FILENO, because it's number is 0
const size_t read_size = 1; // set chunk size
size_t size = read_size;
char *buff = malloc(size+1);
size_t offset = 0;
size_t res = 0;
write(STDOUT_FILENO, "$ ", strlen("$ "));
while((res = read(fd, buff + offset, read_size)) > 0) // read from stdin and save to buff
{
if(res == -1)
{
//read_error();
free(buff);
}
if(buff[offset] == '\n')
{
buff[offset] = '[=12=]';
char **result = parse_cmdline(buff);
if(result[0] != NULL)
{
int exec;
int status;
pid_t pid = fork();
if(pid == -1)
{
//fork_error();
}
else if(pid == 0) // Handle child process
{
if((exec = execvp(result[0], result)) == -1)
{
//file_error(result[0]);
}
}
else
{
waitpid(pid, &status, 0);
}
offset = 0;
free(buff);
buff = malloc(size+1);
size = read_size;
}
free(result);
result = NULL;
write(STDOUT_FILENO, "$ ", strlen("$ "));
}
else
{
offset += res;
buff[offset] = '[=12=]';
if (offset + read_size > size)
{
size *= 2;
buff = realloc(buff, size+1);
}
}
}
free(buff);
return 0;
}
重现错误 1 的方法如下:
启动程序,第一个输入应该是:“/bin/ls -l /usr/include”。之后按回车,再输入任意命令或空行,就会出现错误。
如何重现错误 2:
启动程序和 运行 任何命令。然后 运行 "/bin/ls -l /usr/include" 然后 运行 2个其他命令会出现错误。
注意:使用 Oracle VM VirtualBox,编译:
gcc -Wall -pedantic -std=c11 file.c
./a.out
char **arr = malloc(token_count+1);
没有分配足够的 space。因为没有分配足够的 space,尝试用 token_count+1
指针填充它会超出分配的 space 并破坏内存中的其他数据。
malloc
分配字节数,而不是元素数。它不知道您要分配的元素的大小。所以你必须总是告诉它要分配多少字节。您可以通过将要分配的事物的数量乘以每个事物的大小来实现。
适用于 malloc
的一般模式是:
SomeType *p = malloc(NumberOfThings * sizeof *p);
这是可行的,因为 *p
是内存将包含的对象之一,并且 sizeof *p
产生此类对象所需的字节数。所以在这种情况下你可以使用:
char **arr = malloc((token_count+1) * sizeof *arr);
所以我正在尝试进行 shell 实施,它似乎工作得很好。除了一个非常奇怪的问题。输入命令“/bin/ls -l /usr/include”后出现这些错误:
错误 1:
a.out: malloc.c:2379: sysmalloc: Assertion `(old_top == initial_top (av) && old_size == 0) || ((unsigned long) (old_size) >= MINSIZE && prev_inuse (old_top) && ((unsigned long) old_end & (pagesize - 1)) == 0)' failed. Aborted (core dumped)
错误 2:
realloc(): invalid pointer Aborted (core dumped)
我的代码:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
char **parse_cmdline( const char *cmdline )
{
int token_count = 1;
for(int i = 0; cmdline[i] != '[=12=]';i++)
{
if(cmdline[i] == ' ')
{
token_count++;
}
}
char *token = strtok((char*)cmdline, " ");
char **arr = malloc(token_count+1);
int i;
for(i = 0;token != NULL;i++)
{
arr[i] = token;
token = strtok(NULL, " ");
}
arr[i] = NULL; // make last element NULL for execvp() to work properly
return arr;
}
int main(void)
{
int fd = 0; // set read() to read from STDIN_FILENO, because it's number is 0
const size_t read_size = 1; // set chunk size
size_t size = read_size;
char *buff = malloc(size+1);
size_t offset = 0;
size_t res = 0;
write(STDOUT_FILENO, "$ ", strlen("$ "));
while((res = read(fd, buff + offset, read_size)) > 0) // read from stdin and save to buff
{
if(res == -1)
{
//read_error();
free(buff);
}
if(buff[offset] == '\n')
{
buff[offset] = '[=12=]';
char **result = parse_cmdline(buff);
if(result[0] != NULL)
{
int exec;
int status;
pid_t pid = fork();
if(pid == -1)
{
//fork_error();
}
else if(pid == 0) // Handle child process
{
if((exec = execvp(result[0], result)) == -1)
{
//file_error(result[0]);
}
}
else
{
waitpid(pid, &status, 0);
}
offset = 0;
free(buff);
buff = malloc(size+1);
size = read_size;
}
free(result);
result = NULL;
write(STDOUT_FILENO, "$ ", strlen("$ "));
}
else
{
offset += res;
buff[offset] = '[=12=]';
if (offset + read_size > size)
{
size *= 2;
buff = realloc(buff, size+1);
}
}
}
free(buff);
return 0;
}
重现错误 1 的方法如下: 启动程序,第一个输入应该是:“/bin/ls -l /usr/include”。之后按回车,再输入任意命令或空行,就会出现错误。
如何重现错误 2: 启动程序和 运行 任何命令。然后 运行 "/bin/ls -l /usr/include" 然后 运行 2个其他命令会出现错误。
注意:使用 Oracle VM VirtualBox,编译:
gcc -Wall -pedantic -std=c11 file.c
./a.out
char **arr = malloc(token_count+1);
没有分配足够的 space。因为没有分配足够的 space,尝试用 token_count+1
指针填充它会超出分配的 space 并破坏内存中的其他数据。
malloc
分配字节数,而不是元素数。它不知道您要分配的元素的大小。所以你必须总是告诉它要分配多少字节。您可以通过将要分配的事物的数量乘以每个事物的大小来实现。
适用于 malloc
的一般模式是:
SomeType *p = malloc(NumberOfThings * sizeof *p);
这是可行的,因为 *p
是内存将包含的对象之一,并且 sizeof *p
产生此类对象所需的字节数。所以在这种情况下你可以使用:
char **arr = malloc((token_count+1) * sizeof *arr);