【问题标题】:Array isn't free'd after going out of scope超出范围后数组未释放
【发布时间】:2020-11-10 22:19:02
【问题描述】:

我有一个简单的 char 数组,用于从管道中读取数据。 该数组在无限循环中使用

int main() 
{   
    mkfifo("process1_write", 0666); 
    mkfifo("process1_read", 0666); 
    int fd1,fd2;  
    fd1 = open(process1_write, O_RDWR);
    fd2 = open(process1_read, O_RDONLY| O_NONBLOCK);  
    std::string outmsg  = "{process: drv_rtnode_1, message: hi}";
    while (1) 
    { 
        char str1[1050];
        printf("cycle %d\n\t",i++);
        int in = read(fd2, str1, 1024);
        if(in>0)
        {
            printf("message: %s, in: %d\n", str1, in); 
            write(fd1, outmsg.c_str(), outmsg.size());
        }
        else
            printf("No content received\n");
        sleep(1);
    } 
    return 0; 
} 

如您所见,str1 在堆栈上被实例化为一个局部变量,所以我希望它在每个 while 循环后被释放。

但是我得到的是以下内容:

周期1:从PIPE接收数据,从而进入if(in>0)

message: {"msg type": "status inst", "ProcessName": "process1", "StatusDetail": "dettaglio componente"}{"msg type": "status ses", "ProcessName": "process1", "GroupName": "MOT", "GroupSts": "Online", "ActiveSession": "PRI", "StatusDetail": "dettaglio sessione"}, in: 251

in = 251,所以它计算正确的字符数

周期 2:从 PIPE 接收 LESS 数据

这次我收到这条消息:{"state":"alive"} 但这里是打印输出:

message: {"state":"alive"}tus inst", "ProcessName": "process1", "StatusDetail": "dettaglio componente"}{"msg type": "status ses", "ProcessName": "process1", "GroupName": "MOT", "GroupSts": "Online", "ActiveSession": "PRI", "StatusDetail": "dettaglio sessione"} , in: 17

in = 17,所以字符数再次正确计算,但我的数组根本没有被清空

无论我收到什么样的数据,都会发生这种情况。

我也试过改代码如下:

   char* str1 = new char[1050];
    while (1) 
    { 
        printf("cycle %d\n\t",i++);
        int in = read(fd2, str1, 1024);
        if(in>0)
        {
            printf("message: %s, in: %d\n", str1, in); 
            write(fd1, outmsg.c_str(), outmsg.size());
        }
        else
            printf("No content received\n");
        sleep(1);
        delete[] str1;
        str1 = new char[1050];
    } 

但一切都没有改变。它的行为完全相同。

【问题讨论】:

  • 您需要空终止 c 字符串。看起来您的 read 函数没有这样做。
  • XY 问题。数组IS“被释放”,内存被重新使用。由于数组没有初始化,所以内存没有被触及。该程序具有未定义的行为,因为您没有以空值终止您的字符串。 read 不会为您执行此操作,因为数据可能会通过多次调用到达,并且它不关心您的数据是否为字符串。
  • @kn0bbulo 那么你的问题是什么? I'm receiving this message: {"state":"alive"} 我不明白,在你的代码中有 {process: drv_rtnode_1, message: hi} 但你显示了一些 {"state":"alive"}{"msg type": "status inst... ?这些其他消息来自哪里? receiving LESS data from the PIPE 是的,这就是它的工作原理。但是是否有来自管道的丢失 数据,或者您只接收到部分 数据? printf("message: %s, in: %d\n", str1 当您收到 部分 数据时,str1 不会以零结尾。
  • 您没有使用in 的值来控制打印量。这是真正的问题,与分配或释放无关。 printf 具有可以使用in 的格式说明符,或者可以使用cout.write() 可以使用in 的格式说明符。另外,如果数据嵌入了空值怎么办?无论如何,您的打印方式都会失败,因为 null 会在第一个 null 处停止打印,并且不会写入所有 in 字符。

标签: c++ arrays memory dynamic-memory-allocation


【解决方案1】:

以下内容:

while (1) 
{ 
    char str1[1050];

在函数调用堆栈上分配,但它是这样的:

char str1[1050];
while (1) 
{ 

因此该位置被重用,并且只分配了大约 1050 个字节。

问题是,字符串需要一个 nul 终止符:

   int in = read(fd2, str1, 1024);
   if (in > 0)
   {
       str1[in] = '\0';

现在用较短的数据覆盖不会显示之前的读取。

【讨论】:

  • 好的,刚刚试了一下,效果很好。但是,如果没有 null 终止,这些角色都会一直坐在那里,这让我有点害怕。如果我确实添加了空终止字符,那么所有其他字符会发生什么?它们实际上是被删除了还是仍在消耗内存?
  • @kn0bbulo 这些字符仍然具有不确定的值。它们不会“消耗记忆”。
  • @kn0bbulo 操作系统是高效的。当您“释放”内存时,它不会擦除内存,它只是将其标记为可再次使用。这就是您在第二次迭代中看到旧内容的原因。
  • now that I have to keep track of everything I allocate and deallocate 不要。使用智能指针,std::vectorunique_ptrshared_ptr 是你的朋友。
  • @kn0bbulo 分配数组时,其中的字符是不确定的——它们绝对可以是任何东西。如果它们等于(或不同于)您正在考虑的某个值,请不要感到惊讶。不确定意味着不能保证它们具有(或没有)某些特定值。通常,编译器/运行时将在刚刚释放某些内容的相同位置分配内存,重用以前的值,因为这可能非常有效。这就是这里发生的事情(但不要依赖于此)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多