Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 函数中的旧大小无效_C_Input_Realloc - Fatal编程技术网

C 函数中的旧大小无效

C 函数中的旧大小无效,c,input,realloc,C,Input,Realloc,所以我有这个函数 void getInput(char* input) { char buffer[BUFF_SIZE]; char *buff = buffer; size_t buffersize = 32; getline(&buff, &buffersize, stdin); buffer[strlen(buffer) - 1] = '\0'; strcpy(input, bu

所以我有这个函数

void getInput(char* input) {
        char buffer[BUFF_SIZE];
        char *buff = buffer;
        size_t buffersize = 32;
        getline(&buff, &buffersize, stdin);
        buffer[strlen(buffer) - 1] = '\0';
        strcpy(input, buffer);
}

这个函数被传递一个变量,声明为
char input[BUFF\u SIZE]
,BUFF\u SIZE被定义为
\define BUFF\u SIZE 5000

无论如何,我的错误是,当我在gdb中调试它时,我得到了错误 “/dash”中的
错误:realloc():无效的旧大小:0x00007ffdf5a6fab0***

在使用之后,我将从中获取此信息

#0  0x00002aaaaad05387 in raise () from /lib64/libc.so.6
#1  0x00002aaaaad06a78 in abort () from /lib64/libc.so.6
#2  0x00002aaaaad47ed7 in __libc_message () from /lib64/libc.so.6
#3  0x00002aaaaad4e3e4 in malloc_printerr () from /lib64/libc.so.6
#4  0x00002aaaaad537d1 in _int_realloc () from /lib64/libc.so.6
#5  0x00002aaaaad55c52 in realloc_hook_ini () from /lib64/libc.so.6
#6  0x00002aaaaad3e96b in getdelim () from /lib64/libc.so.6
#7  0x0000000000400f05 in getInput (input=0x7fffffffbae0 "") at dash.c:104
#8  0x0000000000400bbe in main (argc=1, argv=0x7fffffffe308) at dash.c:50

此时我完全不知所措,任何帮助都将不胜感激。

问题是,您无法首先将未分配
malloc
的缓冲区传递到
getline

或者,在调用之前,*lineptr可以包含指向malloc(3)分配的缓冲区*n字节大小的指针。如果缓冲区不够大,无法容纳该行,则getline()使用realloc(3)调整其大小,并根据需要更新*lineptr和*n

getline
认为缓冲区不够大,因为传递的大小是32,所以它进入
realloc
并失败,因为当系统在未分配的
buffer
上调用
realloc
时,它会调用未定义的行为(可能会使应用程序崩溃)

如果
size\u t buffersize=5000,这个bug就会被隐藏,因为
getline
不必重新分配缓冲区(但如果一行大于5000个字符,则仍然是一个错误)

因此,您必须将
buffer
设置为
NULL
,并让
getline
为您分配它

char *buff = NULL;
size_t buffersize = 0;

最后,取消分配
free(buffer)

问题在于,您无法首先将未分配
malloc
的缓冲区传递到
getline

或者,在调用之前,*lineptr可以包含指向malloc(3)分配的缓冲区*n字节大小的指针。如果缓冲区不够大,无法容纳该行,则getline()使用realloc(3)调整其大小,并根据需要更新*lineptr和*n

getline
认为缓冲区不够大,因为传递的大小是32,所以它进入
realloc
并失败,因为当系统在未分配的
buffer
上调用
realloc
时,它会调用未定义的行为(可能会使应用程序崩溃)

如果
size\u t buffersize=5000,这个bug就会被隐藏,因为
getline
不必重新分配缓冲区(但如果一行大于5000个字符,则仍然是一个错误)

因此,您必须将
buffer
设置为
NULL
,并让
getline
为您分配它

char *buff = NULL;
size_t buffersize = 0;
最后,取消分配
free(buffer)

指向
getline()
的指针(指向指针)参数必须可以传递到
free()
。的POSIX规范说明:

应用程序应确保
*lineptr
是可以传递给
free()
函数的有效参数。如果
*n
为非零,应用程序应确保
*lineptr
指向大小至少为
*n
字节的对象,或为空指针

您违反了该限制,因为无法将局部变量
buffer
传递到
free()
。所有的地狱都可能爆发——特别是当你还谎称缓冲区的大小时,声称它只有32字节长,而实际上它有5000字节长(因此对于很短的输入行,需要重新分配)

阅读说明书-遵循说明书中规定的规则

getInput()
函数也不知道函数的
input
参数所指向的缓冲区大小,但它会无条件复制读入
input
缓冲区的所有内容。这是造成缓冲区溢出的原因。您的
getInput()
函数需要一个不同的签名,应该更像:

ssize_t getInput(size_t in_len, char input[in_len])
{
    char *buffer = NULL;
    size_t *buflen = 0;
    ssize_t nbytes;
    if ((nbytes = getline(&buffer, &buflen, stdin)) == -1)
    {
        free(buffer);  // Free any space allocated by getline()
        return EOF;
    }
    if (buffer[nbytes - 1] == '\n'). /* Zap newline if present */
        buffer[--nbytes] = '\0';
    if ((size_t)nbytes >= in_len)
    {
        free(buffer);  // Release space allocated by getline()
        *input = '\0';
        return 0;   // Or another value to indicate an error
    }
    strcpy(input, buffer);
    free(buffer);
    return nbytes;
}
这将告诉您输入缓冲区中有多少字节,从而避免溢出。它确实会复制数据,就像您的原始函数一样——据推测,这对您来说是可以的

请注意,
getline()
返回
-1
,而不是
EOF
(尽管两者通常相同)。它可以(而且通常是这样)在检测EOF之前为空缓冲区指针分配空间,因此即使没有数据,也有必要释放它分配的缓冲区。
getline()
的有效实现从不返回
0
-它返回
-1
或严格的正值。

getline()
的指针(指向指针)参数必须可以传递到
free()
。的POSIX规范说明:

应用程序应确保
*lineptr
是可以传递给
free()
函数的有效参数。如果
*n
为非零,应用程序应确保
*lineptr
指向大小至少为
*n
字节的对象,或为空指针

您违反了该限制,因为无法将局部变量
buffer
传递到
free()
。所有的地狱都可能爆发——特别是当你还谎称缓冲区的大小时,声称它只有32字节长,而实际上它有5000字节长(因此对于很短的输入行,需要重新分配)

阅读说明书-遵循说明书中规定的规则

getInput()
函数也不知道函数的
input
参数所指向的缓冲区大小,但它会无条件复制读入
input
缓冲区的所有内容。这是造成缓冲区溢出的原因。您的
getInput()
函数需要一个不同的签名,应该更像:

ssize_t getInput(size_t in_len, char input[in_len])
{
    char *buffer = NULL;
    size_t *buflen = 0;
    ssize_t nbytes;
    if ((nbytes = getline(&buffer, &buflen, stdin)) == -1)
    {
        free(buffer);  // Free any space allocated by getline()
        return EOF;
    }
    if (buffer[nbytes - 1] == '\n'). /* Zap newline if present */
        buffer[--nbytes] = '\0';
    if ((size_t)nbytes >= in_len)
    {
        free(buffer);  // Release space allocated by getline()
        *input = '\0';
        return 0;   // Or another value to indicate an error
    }
    strcpy(input, buffer);
    free(buffer);
    return nbytes;
}
这将告诉您输入缓冲区中有多少字节,从而避免溢出。