在malloc()'char指针上调用free()会导致程序因无效指针

时间:2016-07-23 18:51:09

标签: c pointers memory-management

当我遇到这个时,我正在学习C并且在堆内存中玩了一下:

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

int main(void) {
    char* test = malloc(1024);
    test = "Hello!";
    printf("%s\n", test);
    free(test);
    return 0;
}

我认为它应该做什么:

  • 在堆上分配1024个字节
  • 将“Hello!\ 0”写入该内存的开头
  • 从我stdout获得的指针开头写入malloc(),直至找到\0
  • 释放用malloc()
  • 分配的1024字节内存
  • 返回0

但是,我的程序在调用free()时崩溃了。为什么呢?

~$ ./mem                                                                                                                                                              
Hello!
*** Error in `./mem': munmap_chunk(): invalid pointer: 0x0000000000400684 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x77725)[0x7f9f99ac5725]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x1a8)[0x7f9f99ad1c18]
./mem[0x4005ec]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f9f99a6e830]
./mem[0x4004e9]
======= Memory map: ========
00400000-00401000 r-xp 00000000 08:01 3801151                            /home/gala/mem
00600000-00601000 r--p 00000000 08:01 3801151                            /home/gala/mem
00601000-00602000 rw-p 00001000 08:01 3801151                            /home/gala/mem
015e6000-01607000 rw-p 00000000 00:00 0                                  [heap]
7f9f99838000-7f9f9984e000 r-xp 00000000 08:01 1970703                    /lib/x86_64-linux-gnu/libgcc_s.so.1
7f9f9984e000-7f9f99a4d000 ---p 00016000 08:01 1970703                    /lib/x86_64-linux-gnu/libgcc_s.so.1
7f9f99a4d000-7f9f99a4e000 rw-p 00015000 08:01 1970703                    /lib/x86_64-linux-gnu/libgcc_s.so.1
7f9f99a4e000-7f9f99c0e000 r-xp 00000000 08:01 1970665                    /lib/x86_64-linux-gnu/libc-2.23.so
7f9f99c0e000-7f9f99e0d000 ---p 001c0000 08:01 1970665                    /lib/x86_64-linux-gnu/libc-2.23.so
7f9f99e0d000-7f9f99e11000 r--p 001bf000 08:01 1970665                    /lib/x86_64-linux-gnu/libc-2.23.so
7f9f99e11000-7f9f99e13000 rw-p 001c3000 08:01 1970665                    /lib/x86_64-linux-gnu/libc-2.23.so
7f9f99e13000-7f9f99e17000 rw-p 00000000 00:00 0 
7f9f99e17000-7f9f99e3d000 r-xp 00000000 08:01 1970637                    /lib/x86_64-linux-gnu/ld-2.23.so
7f9f9a013000-7f9f9a016000 rw-p 00000000 00:00 0 
7f9f9a039000-7f9f9a03c000 rw-p 00000000 00:00 0 
7f9f9a03c000-7f9f9a03d000 r--p 00025000 08:01 1970637                    /lib/x86_64-linux-gnu/ld-2.23.so
7f9f9a03d000-7f9f9a03e000 rw-p 00026000 08:01 1970637                    /lib/x86_64-linux-gnu/ld-2.23.so
7f9f9a03e000-7f9f9a03f000 rw-p 00000000 00:00 0 
7ffcc81cb000-7ffcc81ec000 rw-p 00000000 00:00 0                          [stack]
7ffcc81f8000-7ffcc81fa000 r--p 00000000 00:00 0                          [vvar]
7ffcc81fa000-7ffcc81fc000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
[1]    12941 abort      ./mem

3 个答案:

答案 0 :(得分:3)

欢迎来到C的复杂世界!

基本上,您使用地址test覆盖指针"Hello!"(这是静态不可变数组)。

它崩溃了,因为你试图释放一个你没有创造的东西。

您应该使用strcpy()或循环将字符串复制到text

答案 1 :(得分:3)

正如评论中所说的那样:

int main(void) {
    char* test = malloc(1024);     /* You allocate, great! */
    test = "Hello!";               /* Huh, what's this? You point 'test' 
                                    * to some area in the code section.
                                    * Valid, but considering you just 
                                    * allocated some memory, strange */
    printf("%s\n", test);          /* Print out a string from the code
                                    * section: fine. */
    free(test);                    /* What?! You want to try to free() the
                                    * memory in the code section? That's a 
                                    * big no-no! */
    return 0;                      /* whatever */
}

现在,你应该做什么:

int main(void) {
    char* test = malloc(1024);     /* You allocate, great! */
    strcpy(test, "Hello!");        /* Copy some data into that 
                                    * allocated memory */
    printf("%s\n", test);          /* Print out a string from the
                                    * heap: fine. */
    free(test);                    /* Free that allocated memory! */
    return 0;                      /* aaaand, we're done */
}

答案 2 :(得分:1)

test最初指向由大小为1024的malloc分配的内存。 现在在下一行中,您将测试指向由“Hello!”引用的内存。 所以你的测试指针现在指向“你好!”而不是你首先使用malloc分配的内容。 现在你试图释放“Hello!”,这是无效的,因为没有使用malloc分配这个内存,因此你的编程崩溃了。

public class SpinnerFragment extends Fragment {
    /*private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";
    private String mParam1;
    private String mParam2;*/

    private OnFragmentInteractionListener mListener;
    private View rootView;
    private SearchView teamsSearchView;
    private PopupWindow popupMessage;
    private ArrayAdapter<String> adapter;

    public SpinnerFragment() {
        // Required empty public constructor
    }

    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @param param1 Parameter 1.
     * @param param2 Parameter 2.
     * @return A new instance of fragment SpinnerFragment.
     */
    public static SpinnerFragment newInstance(String param1, String param2) {
        SpinnerFragment fragment = new SpinnerFragment();
        /*Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);*/
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        /*if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }*/
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        rootView = inflater.inflate(R.layout.fragment_spinner, container, false);

        TextView textView = new TextView(getActivity());
        textView.setText("Testing");

        View popup_layout = inflater.inflate(R.layout.popup_layout,container,false);
        ListView teamsListView = (ListView) popup_layout.findViewById(R.id.teams_list_view);

        ArrayList<Team> teamsArrayList = new ArrayList<Team>();
        teamsArrayList.add(new Team(1,"Sharks"));
        teamsArrayList.add(new Team(2,"Android"));
        teamsArrayList.add(new Team(3,"Google"));
        teamsArrayList.add(new Team(4,"Yahoo"));
        teamsArrayList.add(new Team(5,"Facebook"));
        teamsArrayList.add(new Team(6,"Twitter"));
        teamsArrayList.add(new Team(7,"Apple"));
        teamsArrayList.add(new Team(8,"Amazon"));
        teamsArrayList.add(new Team(9,"Udacity"));
        teamsArrayList.add(new Team(10,"Bosch"));

        //adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_dropdown_item_1line,sortList);

        final TeamsAdapter teamsAdapter = new TeamsAdapter(getActivity(), teamsArrayList);

        teamsListView.setAdapter(teamsAdapter);

        popupMessage = new PopupWindow(popup_layout, ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);
        //popupMessage.setContentView(textView);

        teamsSearchView = (SearchView) rootView.findViewById(R.id.teams_search_view);
        teamsSearchView.setQueryHint("Select Team/s");

        teamsSearchView.setOnQueryTextFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View view, boolean hasFocus) {
                Toast.makeText(getActivity(), String.valueOf(hasFocus),
                        Toast.LENGTH_SHORT).show();

            }
        });

        teamsSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {

                Toast.makeText(getActivity(), query,
                        Toast.LENGTH_SHORT).show();

                return true;
            }

            @Override
            public boolean onQueryTextChange(String newText) {

                Toast.makeText(getActivity(), "newText=>"+newText,
                        Toast.LENGTH_SHORT).show();


                if(newText.isEmpty()){
                    popupMessage.dismiss();
                    return false;
                }

                //popupMessage.dismiss();
                if(!popupMessage.isShowing()){
                    popupMessage.showAsDropDown(teamsSearchView);
                }

                teamsAdapter.getFilter().filter(newText);

                /*teamsAdapter.getFilter().filter(newText, new Filter.FilterListener() {
                    @Override
                    public void onFilterComplete(int i) {
                        teamsAdapter.notifyDataSetChanged();
                    }
                });*/
                return true;
            }
        });
        return rootView;
    }


    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnFragmentInteractionListener) {
            mListener = (OnFragmentInteractionListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    public interface OnFragmentInteractionListener {
        void onFragmentInteraction();
    }
}

存储“你好!”在test分配的内存中,需要使用memcpy。 所以代替:

char* test = malloc(1024);
test = "Hello!"; /* This is wrong. You pointer is pointing to "Hello!" string base address */

使用:

test = "Hello!"

这将修复您的代码。