尝试执行“/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);