【问题标题】:Malloc calloc fails to allocate structuremalloc calloc 分配结构失败
【发布时间】:2020-11-26 18:58:53
【问题描述】:

我使用以下 malloc/calloc 代码获得空内存。有时它无法为“name1”分配内存,然后 strcpy 失败。请指导。

struct testMalloc
{
    char name1[90];
    char name2[90]; 
    struct testMalloc* ptr;
};
int main(int argc, char* argv[])
{
    struct testMalloc* test = 0 ;   
    int size = 0;
    size = sizeof(struct testMalloc);

    printf("Size of struct is %d", size);

    test = (struct testMalloc*) calloc(sizeof(struct testMalloc));  
    
    strcpy((test->name1), "hdshdssdsdfsfffffffffffffffffffffffffffffh");

    return 0;

}

【问题讨论】:

  • 指针不能用 0 初始化,而是用 (void*)0 初始化,以防你想获得一个 NULL 指针作为值。否则它是未定义的行为。
  • @alinsoar 你确定吗?你有消息来源吗?
  • @alinsoar 事实上,C 标准委员会最终向那些相信 0 IS NULL 的误入歧途的程序员投降.现在实际上不是 NULL,但 0 是符合 C 标准的空指针常量。
  • @AndrewHenle 在某些系统上我听说空指针不全为 0,但从未见过这样的系统。
  • @alinsoar 0 转换为指针类型时始终为 == NULL。它不必由所有位 0 表示。无论是显式转换 (void *) 还是仅允许它被隐式转换都没有关系。

标签: c malloc calloc


【解决方案1】:

您不包括 <stdlib.h> 以便编译器知道 calloc 的签名,在这种情况下它使用 K&R 调用约定。

如果包含<stdlib.h>,则代码在正确调用calloc之前将无法编译。

【讨论】:

  • @dbush 这并不是反对演员阵容的真正原因,而是程序员失败的原因。
  • 问题是没有包含 stdlib 并且 malloc 被其他一些头文件调用
【解决方案2】:

calloc 有 2 个参数:元素的数量和每个元素的大小。它将清零分配的内存。你要找的是malloc,它只需要一个参数:分配的内存块的总大小,它不会将分配的内存归零。

【讨论】:

    【解决方案3】:
    1. 始终检查 malloc 的结果。
    2. sizeof 中使用对象而不是类型
    3. 尝试使用更安全的字符串函数版本(在此示例中,传递的字符串比数组长。
    4. 您不必强制转换 malloc 的结果,这被认为是不好的做法(现在已经过时了,但无论如何)
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    struct testMalloc
    {
        char name1[20];
        char name2[90]; 
        struct testMalloc* ptr;
    };
    
    struct testMalloc *allocAndCopy(const char *str)
    {
        struct testMalloc *ptr = malloc(sizeof(*ptr));
        if(ptr)
        {
            strncpy(ptr -> name1, str, sizeof(ptr -> name1));
            ptr -> name1[sizeof(ptr -> name1) - 1] = 0;
        }
        return ptr;
    }
    
    
    int main(int argc, char* argv[])
    {
        struct testMalloc* test = allocAndCopy("hdshdssdsdfsfffffffffffffffffffffffffffffh");
    
        if(test) printf("the string is: %s\n", test -> name1);
    }
    

    https://godbolt.org/z/zjvvYW

    【讨论】:

    • 你忘记了allocAndCopy()中的return语句:-)
    【解决方案4】:

    语法错误很少:

    1. struct testMalloc* test = NULL; NULL 指针是这样初始化的
    2. calloc(sizeof(struct testMalloc)); 传递给 calloc 的参数太少。 正确的形式是calloc(no_of_elements, sizeof(type));

    这是您的代码的正确实现:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    struct testMalloc
    {
        char name1[90];
        char name2[90]; 
        struct testMalloc* ptr;
    };
    
    int main(int argc, char* argv[])
    {
        struct testMalloc* test = NULL;
        size_t size = sizeof(struct testMalloc);
    
        printf("Size of struct is %ld\n", size);
    
        if((test = (struct testMalloc*)calloc(1, size)) == NULL){
            return -1; //Failed to allocate memory
        }
        else {
            strcpy((test->name1),"hdshdssdsdfsfffffffffffffffffffffffffffffh");
            printf("%s\n",test->name1);
        }
        
        return 0;
    }
    

    【讨论】:

    • 我会 1. 改用sizeof(*test),这样更灵活,2. 在测试它不是NULL 之前,永远不要访问test。假设分配总是成功是一个常见的错误,但事实并非如此。
    • @IharobAlAsimi malloc()calloc() 使用 sbrk() / brk() 可以更改堆大小。问题主要出现在我们使用mmap() 时,因为我们分配的堆内存几乎与页面一样大。
    • 坚持手册和标准定义。如何实现malloc() 无关紧要。如果由于任何原因失败(可能是特定于实现的),它将返回NULL。永远不要假设。
    • 好吧,我想我可能已经从@IharobAlAsimi 那里学到了一些新的东西,在使用可能不可避免的失败的函数时“永远不要假设”。我会更新答案。
    • 这不是不可避免的问题。这是墨菲定律!
    【解决方案5】:

    从上到下:

    1.

    您忘记使用#include stdlib.h 使用calloc()malloc()。自 C99 起禁止隐式声明。

    2.

    int main(int argc, char* argv[])
    

    您的程序不需要将参数放入其中。

    这个:

    int main (void)
    

    会更合适。

    3.

    int size = 0;
    

    size 永远不应有负值。所以将其声明为unsigned int 甚至更好的size_t 会更合适。

    4.

    struct testMalloc* test = 0 ; 
    

    您可以使用0 来初始化一个指针。它完全有效,因为0 是一个空指针常量。但在处理指针时最好使用NULL,而不是0,以显示指针意图并增加可读性。

    struct testMalloc* test = NULL; 
    

    5.

    calloc(sizeof(struct testMalloc)); 
    

    callocmalloc 相比需要两个参数。第一个需要是项目数,第二个需要是一个项目的大小。

    calloc(sizeof(1,struct testMalloc)); 
    

    6.

    test = (struct testMalloc*) calloc(sizeof(struct testMalloc)); 
    

    您不需要强制转换malloc()calloc() 的返回值。

    7.

    如果分配失败,您忘记检查从calloc() 返回的指向的空指针。始终检查内存管理函数的返回值。

    test = calloc(1, sizeof(struct testMalloc)); 
    if (test == NULL)
    {
        fputs("Allocation failed!", stderr);
        // error routine.
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-22
      • 2011-10-16
      • 2014-07-01
      • 2012-10-08
      • 2018-11-05
      • 2012-08-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多