我已经完成了以下代码,但我找不到有什么问题.该函数getsxnremem()使用字符串获取字符串,len使用fgets()空终止符覆盖换行符(如果有的话),然后重新调整内存大小以适应字符串.无论如何,这是个主意.
以下代码有时会起作用,有时会崩溃.我过去经常发生这种情况,我经常发现问题,但这次我花了太长时间.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
unsigned getsxnremem(char **str, unsigned len){
unsigned l, flag = 1;
free(*str);
char *buff;
if ((*str = malloc(len)) == NULL) return 0;
if(fgets(*str, len, stdin) == NULL) { free(*str); return 0; }
l = strlen(*str);
if (l && ((*str)[l-1] == '\n')) { *(str)[l-1] = '\0'; flag = 0; }
if ((buff = realloc(*str, l + flag)) == NULL){ free(*str); return 0; }
*str = buff;
return (l - 1);
}
int main(void){
char *buff = NULL;
unsigned l = getsxnremem(&buff, 256);
printf("%s\n%u chars long.", buff, l);
}
Run Code Online (Sandbox Code Playgroud)
Sou*_*osh 10
问题是,你没有收集那里的返回值realloc().
根据C11标准,章节§7.22.3.5
#include <stdlib.h>
void *realloc(void *ptr, size_t size);该
realloc函数释放指向的旧对象,ptr并返回指向具有指定大小的新对象的指针size.[...]
realloc()调整内存大小并返回指向新内存的指针.free()考虑到realloc()成功,旧的记忆是d .
所以,
您需要收集并检查返回值realloc()并对其进行测试以确保成功.然后,重新分配给它*str.
注意:请不要使用像那样的表格p = realloc(p, newsize);,如果realloc()失败,你最终也会丢失实际的指针.
如果realloc()成功了,你肯定是没有free()的旧指针.调用free()已经free()-d内存会调用未定义的行为.
{ *(str)[l-1] = '\0'; flag = 0; }
Run Code Online (Sandbox Code Playgroud)
也是错的.您所需的字符串由*str,而不是str.根据运算符优先级,数组下标运算符([])优先于dereference(*)运算符,所以基本上你的代码看起来像
{ * ((str)[l-1]) = '\0'; flag = 0; }
Run Code Online (Sandbox Code Playgroud)
这不是你想要的.因此,为了尊重运算符优先级,您应该像修改它一样
{ (*str)[l-1] = '\0'; flag = 0; }
Run Code Online (Sandbox Code Playgroud)
也就是说,fgets()在使用目标缓冲区之前,还应检查返回值以确保成功.当malloc()返回单元化内存时,如果fgets()失败,您将最终从单元化内存中读取,这将再次导致UB.