局部变量可能指向释放的内存

Posted

技术标签:

【中文标题】局部变量可能指向释放的内存【英文标题】:local variable may point to deallocated memory 【发布时间】:2021-12-20 07:44:31 【问题描述】:

我在标头中有一个结构 (ex3.h)

typedef struct matrix 
    double **data;
    size_t n_rows;
    size_t n_columns;
 matrix;

在 c 文件中,我有函数“create_matrix”和另一个函数切片 我在某些地方收到警告“局部变量可能指向已释放的内存”。我在 cmets 中将它们标记为“--->”

#include <stdlib.h>
# include <stdio.h>
# include "ex3.h"
#define DEBUG
matrix *create_matrix (size_t n_rows, size_t n_columns)

  matrix *mat = malloc (sizeof (matrix));
  if (!mat)
    
      fprintf (stderr, POINTER_ERROR);
      return NULL;
    
  if (n_rows == ZERO || n_columns == ZERO)
     mat->data = NULL, mat->n_rows = ZERO, mat->n_columns = ZERO; 
  else
    
      
        double **mat_data = malloc (n_rows * sizeof (double *));
        if (!mat_data)
          
            free (mat);
            fprintf (stderr, POINTER_ERROR);
            return NULL;
          
        for (int i = ZERO; i < n_rows; i++)
          
            mat_data[i] = malloc (n_columns * sizeof (double));
            if (!mat_data[i])
              
                for (int k = ZERO; k < i; k++)
                  
                    free (mat_data[k]);
                  
                free (mat_data), free (mat);
                fprintf (stderr, POINTER_ERROR);
                return NULL;
              
            else
              
                for (int j = ZERO; j < n_columns; j++)
                  
                    mat_data[i][j] = (double) ZERO;

                  
              
          
        mat->data = mat_data, mat->n_rows = n_rows, mat->n_columns = n_columns;

      
    
  return mat;


matrix *slice (matrix *mat, size_t row_start,
               size_t row_end, size_t col_start, size_t col_end)

 "some condions..."
    
      matrix *m = create_matrix (ZERO, ZERO); //nul matrix
      if (!m) "<---"
        
          return NULL;
        
      return m; "<---"
    
  else
    
      size_t row = row_end - row_start, col = col_end - col_start;
      matrix *new_mat = create_matrix (row, col);
      if (!new_mat)"<---"
        
          return NULL;
        
      for (int i = ZERO; i < row; i++)
        
          for (int j = ZERO; j < col; j++)
            
           "--->"   (new_mat->data)[i][j] = mat->data[i + row_start][j + col_start];
            
        
      return new_mat; "<---"
    

我做了一些条件来确保我不会尝试去内存空间中不属于我的矩阵的空间,那么为什么 clion 仍然发出警告 感谢您的帮助!

【问题讨论】:

乍一看,您的代码似乎正在返回分配的空间或空指针,并在适当的位置检查空指针。这表明报告错误的工具可能是错误的,或者您使用它的源代码可能与您发布的不同。编辑问题以包含minimal reproducible example。将所有代码放在一个序列中,而不是单独的块,这样读者就不必一起编辑片段来编译它们,并在源代码中包含所有必要的语句,例如#include &lt;stdio.h&gt;#include &lt;stdlib.h&gt;... … 然后减少代码;删除不需要重现问题的语句,例如一些没有错误的if/else 子句。然后确保您在此处粘贴的代码正是获取消息的代码。此外,请说明报告错误消息的工具的名称和版本号。那不是克莱恩; CLion 是一个集成开发环境。它就像一个工具箱,可以包含各种工具,它是其中一种工具,而不是 CLion,它会报告错误。该工具可能是编译器或一些代码检查器。 另外,您不能在代码样式中使用**来标记粗体文本。在代码段内,通常的标记字符被禁用,因为它们可能作为源代码的一部分出现。您可以在源代码中添加 cmets 以显示错误消息出现的位置,例如// The following line gets an error message. new_mat 大小:row_end-row_start+1 列同上 @ptitXav 这是新行 = [开始,结束) 【参考方案1】:

我会换一种方式。取而代之的是大量的分配,我只会使用一个。我会使用正面测试而不是负面测试(即有什么问题),并且该函数只有一个返回点。

typedef struct matrix 
    size_t n_rows;
    size_t n_columns;
    double data[];
 matrix;

matrix *allocate(size_t r, size_t c)

    matrix *m = malloc(sizeof(*m) + r * c * sizeof(m -> data[0]));
    if(m)
    
        m -> n_rows = r;
        m -> n_columns = c;
    
    return m;


matrix *slice(matrix *m, size_t sr, size_t er, size_t sc, size_t ec)

    matrix *result = NULL;
    size_t lc = ec - sc, lr = er - sr;
    if(m && m -> n_rows > er && m -> n_rows > sr && sr <= er && m -> n_columns > ec && m -> n_columns > sc && sc <= ec)
    
        result = allocate(lr, lc);
        if(result)
        
            double (*dest)[lc] = &result -> data;
            double (*src)[m -> n_columns] = &m -> data;

            result -> n_rows = lr;
            result -> n_columns = lc;
            for(size_t row = 0; row < lr; row ++)
            
                memcpy(dest[row], &src[sr + row][sc], lc * sizeof(m -> data[0]));
            
        
    
    return result;

【讨论】:

你确定:double (*dest)[lc] = &result-> data; ? @PtitXav 是的,我确定 任何 dv 解释? 本帖不回答问题(为什么会发出警告)并且破坏了代码的语义(原代码支持零大小矩阵;当任一维度为零时,例程不返回一个空指针,但返回一个指向描述空矩阵的结构的指针,这显然是基于专用于它的代码故意的)。 附加小注:m -&gt; n_rows &gt; er &amp;&amp; m -&gt; n_rows &gt; sr &amp;&amp; sr &lt; er 是多余的,因为m-&gt;n_rows &gt; er &amp;&amp; sr &lt; er 意味着m-&gt;n_rows &gt; srmemcpy(dest[row], &amp;src[sr + row][sc], lc * sizeof(m -&gt; data[0]) 可以是 memcpy(dest[row], &amp;src[src + row][sc], sizeof dest[row])size_t lc = ec - sc, lr = er - sr; 在需要它们的范围之外声明标识符;它们可以在if 内。

以上是关于局部变量可能指向释放的内存的主要内容,如果未能解决你的问题,请参考以下文章

函数返回局部变量

全局变量局部变量静态全局变量静态局部变量在内存里的区别

指针函数不可以返回局部变量地址解决

从 JavaScript 中的局部变量释放内存

(二十六)成员变量与局部变量

java语言中,类的成员变量分配在哪个内存区?