C 现有数据正在丢失

C 现有数据正在丢失,c,gnu,C,Gnu,我正在学习c语言。下面的程序将命令的输出获取到变量并打印它。但是当重新分配内存以扩展内存时,我丢失了旧数据 你能告诉我我在这里遗漏了什么吗 #include<stdio.h> #include<stdlib.h> #include<string.h> int main(){ FILE *fp; char r[1024]; fp=popen("/bin/ls /etc/","r"); if(fp==NULL){ perror("Failed to

我正在学习c语言。下面的程序将命令的输出获取到变量并打印它。但是当重新分配内存以扩展内存时,我丢失了旧数据

你能告诉我我在这里遗漏了什么吗

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

int main(){

FILE *fp;

char r[1024];
fp=popen("/bin/ls /etc/","r");

if(fp==NULL){
    perror("Failed to run the command");
    exit(-1);
}

int totallengthread=0,alloc_size=1024;
char *buffer = (char*) malloc(alloc_size*sizeof(char));
memset(buffer,0,sizeof(buffer));
int lenofbuff=0;
while(fgets(r,1023,fp)!=NULL){
 concat(buffer,r);
 lenofbuff=strlen(buffer);
 totallengthread+=lenofbuff;
 if(totallengthread>=alloc_size){
     alloc_size+=1024;
     realloc(buffer,alloc_size);
 }

}
pclose(fp);
printf("this is the out put =>%s",buffer);
free(buffer);
 return 0;
}
void concat(char *dest, const char *source){
    char *d=dest;
    char *s=source;
    while (*d != '\0') {
              d++;
           }
     while(*s!='\0')
        {
            *d++=*s++;
        }
    *d='\0';
}
#包括
#包括
#包括
int main(){
文件*fp;
charr[1024];
fp=popen(“/bin/ls/etc/”,“r”);
如果(fp==NULL){
perror(“未能运行命令”);
出口(-1);
}
int totalengthread=0,alloc_size=1024;
char*buffer=(char*)malloc(alloc_size*sizeof(char));
memset(buffer,0,sizeof(buffer));
int lenofbuff=0;
while(fgets(r,1023,fp)!=NULL){
concat(缓冲液,r);
lenofbuff=strlen(缓冲区);
totallengthread+=lenofbuff;
如果(TotalEngThread>=所有尺寸){
alloc_大小+=1024;
realloc(缓冲区、分配大小);
}
}
pclose(fp);
printf(“这是输出=>%s”,缓冲区);
自由(缓冲);
返回0;
}
void concat(char*dest,const char*source){
char*d=dest;
char*s=源;
而(*d!='\0'){
d++;
}
而(*s!='\0')
{
*d++=*s++;
}
*d='\0';
}
realloc()
是通用内存重新分配的构建块

代码需要使用来自realloc()的返回值,因为这是成功时指向重新分配数据的指针

void * tptr = realloc(buffer, alloc_size);
// Detect out-of-memory 
if (tptr == NULL && alloc_size > 0) {
  // Handle it in some way
  fprintf(stderr, "Memory allocation failure\n");
  exit(EXIT_FAILURE);
}

buffer = tptr;


注意:存在各种其他非分配代码问题。

我认为这更接近您想要的。请参见代码中的注释

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

void concat(char *dest, const char *source){
    char *d=dest;
    char *s=source;
    while (*d != '\0'){
        d++;
    }
    while(*s!='\0'){
        *d++=*s++;
    }
    *d='\0';
}

int main(){
    FILE *fp;
    char r[1024];
    fp=popen("/bin/ls /etc/","r");
    if(fp==NULL){
        perror("Failed to run the command");
        exit(-1);
    }
    int totallengthread=0,alloc_size=1024;
    char *buffer = malloc(alloc_size*sizeof*buffer); //This is nicer because is type independent
    memset(buffer,'\0',sizeof*buffer); //I believe this is what you wanted.
    int lenofbuff=0;
    while(fgets(r,sizeof r,fp)){ // as @chux said this avoids hardcoding 1024-1. You also don't need to compare to NULL. 
        concat(buffer,r);
        lenofbuff=strlen(buffer);
        totallengthread+=lenofbuff;
        if(totallengthread>=alloc_size){
            alloc_size+=1024;
            buffer = realloc(buffer,alloc_size); //you need to use the return of realloc
        }
    }
    pclose(fp);
    printf("this is the out put =>%s",buffer);
    free(buffer);
    return 0;
}
相当于

memset(buffer,0,sizeof*buffer);
正如@thebusybee提到的,这只是将数组的第一个元素设置为空字符,如果您打算填充整个数组,那么您应该这样做 memset(缓冲区,0,缓冲区的分配大小)

或者仅仅是替换

char *buffer = malloc(alloc_size*sizeof*buffer);
memset(buffer,0,alloc_size*sizeof*buffer);
为了


这一行:
memset(buffer,0,sizeof(buffer))
并不像您想象的那样。(这也是不必要的。)您应该在
concat(buffer,r)之前检查缓冲区大小(并重新分配)
而不是
fgets
和后续的
strlen
,您应该使用
fread
读取数据并使用返回值。阅读函数的文档肯定会有帮助:
man realloc
或查找@willampersell-使用
fread()而不是
fgets()的问题
是指
fread()
不注意线路,除非输入恰好来自终端或管道。如果要求
fread()
从磁盘文件中读取1023个字符,它会这样做,除非在此之前有EOF。使用POSIX返回长度,包括空字节,这也是
fgets()
的一个问题;它有着微妙不同的缺点(单行线太大了,不太舒服)。
memset()
仍然是错误的,因为
sizeof*buffer
等于
sizeof buffer[0]
等于
sizeof(char)
是1。它必须是
memset(buffer,'\0',allocsize*sizeof buffer[0])
malloc()
memset(…,0,…)
的组合可以替换为
calloc()
,顺便说一句。@thebusybee我同意这是将整个分配内存设置为0的正确方法,但这是假设OP想要将整个内存而不是第一个字符设置为
'\0'
很好。我被“代码> MeMSET())/<代码>所误导,我从来没有考虑过用它来设置一个元素。我会使用
buffer[0]='\0'当然。
while(fgets(r,1023,fp)!=NULL){
以一种正常的方式关闭。建议
while(fgets(r,sizeof r,fp)!=NULL){
或者干脆
while(fgets(r,sizeof r,fp)){
@chux True,硬编码的1023不是很好。我只是试图解决与OP的问题最密切相关的问题,但确实我可以补充一下。
char *buffer = malloc(alloc_size*sizeof*buffer);
memset(buffer,0,alloc_size*sizeof*buffer);
char *buffer = calloc(alloc_size,sizeof*buffer);