2

私のアプリは stlinux (sh4) で使用されていますが、残念ながら valgrind は sh4 cpu をサポートしていません。アプリでメモリ リークが発生したため、mtrace を使用したところ、一部のメモリが解放されていないことが確認されました。問題は、戻り値で使用される malloc の変数であるため、どうすればそれを解放できるかわかりません (解放された場合、関数での戻り値は無意味になるため)。

私はcs_mallocを書きました(上記のリンクのoscam-simple.cから以下のコードを入れてください)、mtraceログは次のように述べています:

*tmp = malloc (size);

メモリが空いていません

 /* This function encapsulates malloc. It automatically adds an error message to the log if it failed and calls cs_exit(quiterror) if quiterror > -1. 
       result will be automatically filled with the new memory position or NULL on failure. */
    void *cs_malloc(void *result, size_t size, int32_t quiterror){
        void **tmp = result;
        *tmp = malloc (size);
        if(*tmp == NULL){
            cs_log("Couldn't allocate memory (errno=%d %s)!", errno, strerror(errno));
            if(quiterror > -1) cs_exit(quiterror);
        } else {
            memset(*tmp, 0, size);  
        }
        return *tmp;
    }

そして、malloc の場合は、次のように呼び出します。

  // create the AES key entry for the linked list
    if(!cs_malloc(&new_entry, sizeof(AES_ENTRY), -1)) return;

これらの 3 つの関数を見てください (malloc は無料ではありません。他のユーザーが言ったように、valgrind はこれらのコードがメモリ リークを引き起こすと主張しています module-datastruct-llist.c

メモリ リークは、次の 3 つの異なる部分によって発生します。

  1. 以下のコードでは、「new」は解放されませんが、その関数の代わりに使用されるため、どうすれば解放できるかわかりません。

    LL_NODE* ll_append_nolock(LLIST *l, void *obj)
    {
    if (l && obj) {
        LL_NODE *new;
        if(!cs_malloc(&new,sizeof(LL_NODE), -1)) return NULL;
        new->obj = obj;
    
        if (l->last)
            l->last->nxt = new;
        else
            l->initial = new;
        l->last = new;    
    
        l->count++;
        return new;
        }  
        }
    
  2. また、以下の関数で「l」を使用していますが、これもreturn関数で使用しているため、解放する方法がわかりません。:

      LLIST *ll_create()
      {
       LLIST *l = cs_malloc(&l, sizeof(LLIST), 0);
       pthread_mutex_init(&l->lock, NULL);
       return l;
       }
    
  3. new と同じ話:

             LL_NODE *ll_prepend(LLIST *l, void *obj)
            {             
            if (l && obj) {
    
            LL_NODE *new;
            if(!cs_malloc(&new,sizeof(LL_NODE), -1)) return NULL;
    
            new->obj = obj;
            ll_lock(l);
            new->nxt = l->initial;
    
            l->initial = new;
            if (!l->last)
                l->last = l->initial;
            l->count++;
            ll_unlock(l);
    
            return new;
        }
           return NULL;
        }
    

その他の機能については、module-datastruct-llist.cを参照してください。

専門家が教えてくれたら、どうすればそのメモリリークを修正できるかを非常に高く評価します(cs_mallocを書き直す必要がある、または新しい関数を追加する必要があると感じた場合は、意味するソースコードを書いてください.

4

3 に答える 3

0

@Anders返信ありがとうございます。あなたのメモを考慮します。メモリリークがどのようになるかを説明したように変更します...

どのように、この行は、あなたが書いた新しい cs_malloc 関数に変更する必要があります: 1.

    LLIST *l = cs_malloc(&l, sizeof(LLIST), 0);
    pthread_mutex_init(&l->lock, NULL);
    return l;

2.

if(!cs_malloc(&para,sizeof(struct read_thread_param), -1)) return FALSE;
            para->id=i;
于 2012-10-16T22:23:00.787 に答える
0

malloc の最も一般的な実装では、グローバルなヒープ メモリが使用されるため、最終的に解放される前に、複数の関数間で 1 つの場所に割り当てられたストレージが渡されることが非常に一般的です。

たとえば、malloced リターンを無視する ll_append_nolock の呼び出しがあります。いえ

ll_append_nolock(it->l, obj);

したがって、リークを回避するには、他の場所で行っていることを行う必要があります。つまり、呼び出し元の関数が割り当てられたメモリをポインターに受け取るようにします。

LL_NODE *n = ll_append_nolock(l, obj);
/* do stuff with "n", which points to memory allocated under the name of "new" */
free(n);

そして、n (上記のように、「新しい」という名前で割り当てられたストレージを指します。つまり、同じメモリ、異なる名前) を使い終わったら、それを解放します。

HTH。

于 2012-10-16T19:24:12.517 に答える
0

ただし、関数cs_mallocの最初のパラメーターはresult、関数で割り当てられることはありませんcs_malloc

後でcs_mallocこのように使用します

if(!cs_malloc(&new,sizeof(LL_NODE), -1)) return NULL;
    new->obj = obj;

「new」が初期化されていないため、これは機能しません

割り当てに失敗した場合は、結果に代入するか、代わりに単に返すだけcs_mallocでブロックを返す必要があります。cs_mallocNULL

例えば

void *cs_malloc(size_t size, int32_t quiterror)
{
  void* tmp = calloc(1,size);
  if(tmp == NULL)
  {
    cs_log("Couldn't allocate memory (errno=%d %s)!", errno, strerror(errno));
    if(quiterror > -1) cs_exit(quiterror);
  } 
  return tmp;
}

  if (new = cs_malloc(sizeof(LL_NODE),-1))
  {
    new->obj = obj;
  }
  else
  {
    return NULL;
  }
于 2012-10-16T20:49:23.340 に答える