在释放内存的同时堆积腐败

时间:2015-05-31 12:11:26

标签: c heap-corruption

我正在努力解决这段代码问题。顾名思义,函数应返回字符串数组,表示作为参数给出的字符串的所有旋转。

package shop.ned.shahbaa;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;


public class Item1 extends ActionBarActivity {

    private ArrayAdapter<String> adapter;
    private Button add;
    private ListView cart;
    private ArrayList<String> item;
    private EditText et;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_item1);

        add = (Button)findViewById(R.id.buttonConfirmAddProduct);
        cart = (ListView)findViewById(R.id.listView);
        et = (EditText) findViewById(R.id.editTextQuantityAddProduct);
        item = new ArrayList<String>();
        for (int i=0;i<2;i++){
            item.add("Row:" + i);
        }
        adapter = new ArrayAdapter<String>(getApplicationContext(),android.R.layout.simple_list_item_1, item);
        cart.setAdapter(adapter);
        add.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                item.add(et.getText().toString());
                adapter.notifyDataSetChanged();
            }
        });

    }
}

从算法的角度来看它可以很好地工作,但是这个函数的简单调用

char **str_all_rotations(const char *data) 
{
    int i = 0; /* Loop counter */ 
    len = strlen(data); /* Len of input */ 

    /******************/
    /*  malloc memory */

    char **all_rotations = (char**)malloc(sizeof(char*)* len);
    char *double_data = (char*)malloc(len * 2 * sizeof(char));

    for (i = 0; i < len; i++) 
    {
         all_rotations[i] = (char*)malloc(sizeof(char)* len);
    }

    /*******************/
    /*  Rotations part */

    strcpy(double_data, data);
    strcpy(double_data + len, data);

    for (i = 0; i < len; i++) 
    {
        strncpy(all_rotations[i], double_data + i, len);
        all_rotations[i][len] = '\0';
    }

    free(double_data); /* Release memory */

    return all_rotations;
}
由于堆损坏,

失败。我看不出什么是错的。 如何调试这种错误?

1 个答案:

答案 0 :(得分:2)

您的代码存在一些问题

  1. 使用时

    strcpy(double_data + len, data);
    

    你将一个额外的字节复制到double_data,你没有为其分配空间的nul终结符,所以你应该像这样分配空间

    char *double_data = malloc(2 * len + 1));
    
  2. 同样适用于for循环中的分配,即

    all_rotations[i] = (char*)malloc(sizeof(char)* len);
    

    当然修复将是

    all_rotations[i] = malloc(1 + len);
    
  3. 您永远不会检查malloc()是否返回NULL,这是不好的做法。

  4. Do not cast the return value of malloc()

  5. 不要使用strlen()作为循环的条件,除非字符串的长度在循环内发生变化,因为strlen()计算每次调用时字符串的长度,所以你是制作O(n)算法O(n 2 )。

  6. 该标准要求sizeof(char) == 1,因此只会使代码混乱。

  7. 这是您自己修复的代码,用于解决上述问题

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    char **
    str_all_rotations(const char *const data)
     {
        int    index;
        char **all_rotations;
        char  *double_data;
        int    length;
    
        if (data == NULL)
            return NULL;
        length        = strlen(data);
        index         = 0;
        all_rotations = malloc(length * sizeof(*all_rotations));
        if (all_rotations == NULL)
            return NULL;
        double_data = malloc(2 * length + 1);
        if (double_data == NULL)
            goto cleanup;
        for (index = 0 ; index < length ; index++)
         {
            all_rotations[index] = malloc(1 + length);
            if (all_rotations[index] != NULL && index < 4)
                continue;
            goto cleanup;
         }
        memcpy(double_data, data, length);
        memcpy(double_data + length, data, length);
    
        double_data[2 * length] = '\0';
        for (index = 0 ; index < length ; index++)
         {
            memcpy(all_rotations[index], double_data + index, length);
            all_rotations[index][length] = '\0';
         }
        free(double_data);
    
        return all_rotations;
    
    cleanup:
        while (index >= 0)
            free(all_rotations[index--]);
        free(all_rotations);
        free(double_data);
    
        return NULL;
     }
    
    int
    main(void)
     {
        char  *str  = "omgillsetyouonfire";
        char **asdf = str_all_rotations(str);
    
        if (asdf != NULL)
         {
            for (int i = 0 ; str[i] != '\0' ; i++)
             {
                printf("%s\n", asdf[i]);
                free(asdf[i]);
             }
            free(asdf);
         }
    
        return 0;
     }