【问题标题】:Why does realloc fail on repeated calls where as allocating a big chunk using malloc works?为什么在使用 malloc 分配大块的情况下重复调用时 realloc 会失败?
【发布时间】:2012-10-16 16:47:58
【问题描述】:

我正在尝试从标准输入读取(从文件中传递值)。我正在从字符串中读取每个字符并将其存储到动态分配的字符串指针中。需要时我重新分配内存。我正在尝试获得尽可能多的字符。虽然我可以将其限制为 100,000 个字符。但是在一些迭代之后 realloc 失败了。但是如果我在 malloc 的第一次初始化期间指定一个大的块大小,比如 1048567,我可以完全读取字符串。这是为什么呢?

下面是我的程序:

#include <stdio.h>
#include <stdlib.h>

int display_mem_alloc_error();

enum {
    CHUNK_SIZE = 31    //31 fails. But 1048567 passes.
};

int display_mem_alloc_error() {
    fprintf(stderr, "\nError allocating memory");
    exit(1);
}

int main(int argc, char **argv) {
    int numStr;                  //number of input strings
    int curSize = CHUNK_SIZE;    //currently allocated chunk size
    int i = 0;                   //counter
    int len = 0;                 //length of the current string
    int c;                       //will contain a character
    char *str = NULL;            //will contain the input string
    char *str_cp = NULL;         //will point to str
    char *str_tmp = NULL;        //used for realloc

    str = malloc(sizeof(*str) * CHUNK_SIZE);
    if (str == NULL) {
        display_mem_alloc_error();
    }    
    str_cp = str;   //store the reference to the allocated memory

    scanf("%d\n", &numStr);   //get the number of input strings
    while (i != numStr) {
        if (i >= 1) {   //reset
            str = str_cp;
            len = 0;
            curSize = CHUNK_SIZE;
        }
        c = getchar();
        while (c != '\n' && c != '\r') {
            *str = (char *) c;
            //printf("\nlen: %d -> *str: %c", len, *str);
            str = str + 1;
            len = len + 1;
            *str = '\0';
            c = getchar();
            if (curSize / len == 1) {
                curSize = curSize + CHUNK_SIZE;
                //printf("\nlen: %d", len);
                printf("\n%d \n", curSize);    //NB: If I comment this then the program simply exits. No message is displayed.
                str_tmp = realloc(str_cp, sizeof(*str_cp) * curSize);
                if (str_tmp == NULL) {
                    display_mem_alloc_error();
                }
                //printf("\nstr_tmp: %d", str_tmp);
                //printf("\nstr: %d", str);
                //printf("\nstr_cp: %d\n", str_cp);
                str_cp = str_tmp;
                str_tmp = NULL;
            }
        }
        i = i + 1;
        printf("\nlen: %d", len);
        //printf("\nEntered string: %s\n", str_cp);
    }
    str = str_cp;
    free(str_cp);
    free(str);
    str_cp = NULL;
    str = NULL;
    return 0;
}

谢谢。

【问题讨论】:

  • 请注意,sizeof (char) 始终为 1,因此在内存分配调用中添加使用它通常被认为是一个坏主意。除了人类阅读代码的噪音之外,它不会增加任何东西(你乘以 1)。

标签: c string malloc realloc


【解决方案1】:

当你realloc

str_tmp = realloc(str_cp, sizeof(*str_cp) * curSize);
if (str_tmp == NULL) {
    display_mem_alloc_error();
}
//printf("\nstr_tmp: %d", str_tmp);
//printf("\nstr: %d", str);
//printf("\nstr_cp: %d\n", str_cp);
str_cp = str_tmp;
str_tmp = NULL;

你让str_cp 指向新的内存块,但str 仍然指向旧的,现在是freed 块。因此,当您在下一次迭代中访问 str 指向的内容时,您会调用未定义的行为。

您需要保存str 相对于str_cp 的偏移量,并在重新分配后,让str 在其旧偏移量处指向新块。

*str = (char *) c; 是错误的,尽管它在功能上等同于正确的*str = c; 的可能性非零。

【讨论】:

  • str_cp = str_tmp; 之后,我添加了str = str_cp + len;,正如你提到的,程序运行良好。哇!谢谢大家。
【解决方案2】:
     *str = (char *) c;

这一行是错误的。

str 是指向 char 的指针,*strchar,但您将指向 char 的指针分配给 char。这不能在 C 中完成。

此外:

scanf("%d\n", &numStr);

scanf 调用中的 \n 可能与您期望的不同:

http://c-faq.com/stdio/scanfhang.html

还有:

str = str_cp;
free(str_cp);
free(str);

你在这里有一个双重免费。赋值后strstr_cp 将具有相同的值:

free(str_cp);
free(str);

就像你这样做:

free(str);
free(str);

这是未定义的行为(你不能释放两次)。

【讨论】:

  • 不是*s = 'a';正确的?我正在取消引用指针并将值保存到 s 指向的位置,对吗?在上述情况下,由于 c 是 int,我将其转换为 char,不是吗?不是和s[0] = (char*)c;一样吗?
  • @kadaj 不。您似乎认为右侧的星号无关紧要,但确实如此!转换为 (char) 与转换为 (char *) 不同。前者是“字符”,后者是“字符指针”。将int 转换为指针通常不是正确的做法。
  • 哦!使用 (char) 没问题,对吧?但是程序pastebin.com/Gd0Nyv0z 似乎可以工作。但这可能是未定义的行为。我得到了那个铸造错误。
猜你喜欢
  • 2017-08-19
  • 2014-05-31
  • 1970-01-01
  • 2016-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-27
相关资源
最近更新 更多