我的指针错误在哪里?

Kor*_*era 2 c realloc

我已经完成了以下代码,但我找不到有什么问题.该函数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 .

所以,

  1. 您需要收集并检查返回值realloc()并对其进行测试以确保成功.然后,重新分配给它*str.

    注意:请不要使用像那样的表格p = realloc(p, newsize);,如果realloc()失败,你最终也会丢失实际的指针.

  2. 如果realloc()成功了,你肯定是没有free()指针.调用free()已经free()-d内存会调用未定义的行为.

在此之后,由于正确地在提到其他的答案dbush,使用

 { *(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.