【问题标题】:calloc vs memset one shows resulzs and one doesn'tcalloc vs memset 一个显示结果,一个没有
【发布时间】:2021-02-22 13:39:39
【问题描述】:

所以我正在尝试深入研究 C,以下是处理内存分配、文件和字符串/指针的代码。我已经使用 callocate 和 memset 尝试过。 callocate 似乎工作正常,但 memset 不是。 代码的思路如下:我创建了一些文件,每次创建一个文件时,它的名称都会被推送到一个列表中。我有固定数量的文件要保留。并且在用完该数字后,每次创建新文件时都会删除最旧的文件。 使用 calloc 时。打印显示正确的消息,我的文件夹有最后数量的文件: 这是代码:

#include <stdio.h>
#include <stdlib.h>   // needed for malloc
#include <string.h>   // needed for strcpy
#include <unistd.h>

#define  Extension                         ".txt"
#define LOG_MIN_FILENAME_SIZE               32
#define  NBR_OF_FILES                        6

char buffer[LOG_MIN_FILENAME_SIZE];   
                                     
int timez = 0;
int minutes = 0;
int NUM_OF_EXISTING_FILES=0;


FILE *pf = NULL;
char* ListOfFiles[NBR_OF_FILES];
int status;



int main(void){
    
 for(int i=0; i<NBR_OF_FILES;i++){

ListOfFiles[i] = calloc(LOG_MIN_FILENAME_SIZE + 1, 1);




  for(int i=0; i<10;i++) { 
  
  
    pf =fopen(buffer, "w");
    sprintf(buffer, "%d""%d"Extension, minutes, timez);
    
    if(access(buffer, F_OK)==-1){
        
        NUM_OF_EXISTING_FILES++;
        fclose(pf); //closing the files is necessary
        if(NUM_OF_EXISTING_FILES >= NBR_OF_FILES){
                status = remove(ListOfFiles[0]);
                printf("removed");  
                }
        
        
        for(int i=0; i < NBR_OF_FILES-1; i++){
                strcpy(ListOfFiles[i], ListOfFiles[i+1]);// u cant use just normal assignment because it copies the head ot the pointer rather than the actual content of it
        }
    
        strcpy(ListOfFiles[NBR_OF_FILES-1], buffer);
    }
        
    timez++;
    minutes++;
    
    }
    
    for(int i=0; i<NBR_OF_FILES-1; i++){
        printf("%s", ListOfFiles[i]);
    }
}

现在上面的代码就像我说的那样工作,但是一旦我用这个替换了 calloc 行:

    (void) memset(ListOfFiles[i], 0 ,LOG_MIN_FILENAME_SIZE + 2);
 }

代码没有显示任何内容,也没有创建文件。 memsetcalloc 有什么区别,为什么它不适合我?

【问题讨论】:

  • calloc 分配零初始化数据,而 memset 只是将已分配的数据设置为某个字节值。除非数据已经分配,​​否则您不能使用 memset,它可能会导致您的应用程序崩溃。
  • the code above works?没办法,segmentation fault is all I can get。就行了memset(ListOfFiles[i] - ListOfFiles[i] 是 NULL。
  • memset 不分配内存。 Int 只填充它。如果你之前调用malloc() 可以使用它(malloc() 分配内存但不初始化它所以p=malloc(n) + memset(p,0,n) 相当于p=calloc(n,1)
  • 这段代码实际上没有将ListOfFiles设置为除NULs之外的任何值(使用memset时不正确,calloc-ing时正确)。无论哪种方式,您的“文件列表”都没有名称。我强烈怀疑,在尝试创建minimal reproducible example 的过程中,您删除了使其工作的代码部分。
  • @shadowranger 如果您尝试代码,您肯定会看到 calloc 正在完成这项工作。我不是代码背后发生的事情的专家。但是从执行来看,最后ListOfValues内容的printf返回的是正确的字符串。

标签: c memory allocation


【解决方案1】:

这是有问题的:

char* ListOfFiles[NBR_OF_FILES];
memset(ListOfFiles[0], ...);

memset 期望它的第一个参数是指向它将修改的缓冲区的指针。但是ListOfFiles[0]NULL[1]。不会有什么好事。具体来说,是未定义的行为导致现代通用计算机上出现 SIGSEGV(崩溃)。

calloc,另一方面,分配一个缓冲区并返回一个指向它的指针。这确实是正确的做法。


  1. 因为ListOfFiles 是在静态存储中找到的,因为它是全局的。在其他情况下,它可能未初始化,情况更糟。

【讨论】:

  • 注意:可能会更糟。至少ListOfFiles 是全球性的,它保证充满NULLs。如果它在堆栈上,它将充满随机堆栈碎屑,并且在某些情况下可能会起作用,而在其他情况下会产生令人费解的错误。
  • ListOfFiles[0] 为 null 或未定义,具体取决于我们所讨论的 c/c++ 标准。
  • @Sven Nilsson,我的印象是静态存储中的变量被初始化为好像使用了= 0。如果不正确,请随时提供详细信息。
  • @ShadowRanger Re "至少ListOfFiles 是全球性的,它肯定会充满NULLs",是的,我打算避免提及保持简单,但我现在添加了一个脚注。
  • @SvenNilsson:是吗? CC++ 似乎都保证任何具有静态存储持续时间(includes all globals)的东西都是零初始化、默认初始化或它们的某种组合。
猜你喜欢
  • 1970-01-01
  • 2016-12-05
  • 2013-11-14
  • 2021-02-24
  • 2017-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多