释放在返回指向该内存的指针的函数中分配的内存(C ++)

时间:2014-02-28 01:39:07

标签: c++

当我尝试删除“z”时出现堆损坏错误。我假设z指向分配的内存,所以我很困惑为什么delete []会产生错误。

char* cpytoheap(const char* y)
{
    char* x = new char;
    for (int i=0; *(y+i); i++)
    {
        *(x+i) = *(y+i);
        *(x+i+1) = '\0';
    }
    return x;
}


int main()
{
    char* z = "asdf";
    z = cpytoheap(z);
    cout << z; //check that "asdf" copied correctly
    delete[] z; //error doesn't occur if this is taken out
    char y; //keep window open
    cin >> y; //...
    return 0;
}

我没有在cpytoheap中使用下标,因为练习是在不使用下标的情况下复制到免费商店。我通常会继续前进,但我觉得将来知道如何在这种情况下释放记忆可能很重要。

3 个答案:

答案 0 :(得分:6)

您只为x分配了1个字符。将其改为

char *x = new char[strlen(y)+1];

确保为内容分配足够的内存空间。

答案 1 :(得分:1)

您使用strdupa分配z,它将结果动态分配到堆栈。因此,它应该不被释放;当前函数返回时,它将自动释放。从这个意义上说,strdupa类似于在当前函数中声明一个本地字符串变量。

您收到“堆损坏”错误,因为您的对象根本没有在堆上声明(free查看堆栈分配的内存并且没有看到任何分配标记,因此它假定内存区域已损坏。)


此外,在任何情况下,您都不会使用delete[]来释放从C函数分配的对象;如果您需要释放此类结果,请始终使用free

答案 2 :(得分:0)

您的程序有两个错误:

  1. 您在函数cpytoheap()中分配的内存不足。
  2. 您已使用new分配了内存,因此您应该使用delete。如果您使用new []分配,则只使用delete []。
  3. 要了解这些问题,您可以在Windows平台上使用GNU / Linux上的valgrind或Windows上的WinDBG / PageHeap。 valgrind为您的程序生成以下报告。

    mantosh@mantosh4u:~$ valgrind ./a.out
    ==4575== Memcheck, a memory error detector
    ==4575== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
    ==4575== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
    ==4575== Command: ./a.out
    ==4575== 
    ==4575== Invalid write of size 1
    ==4575==    at 0x400A12: cpytoheap(char const*) (pratice.cpp:10)
    ==4575==    by 0x400A4E: main (pratice.cpp:19)
    ==4575==  Address 0x5a08041 is 0 bytes after a block of size 1 alloc'd
    ==4575==    at 0x4C2B1C7: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==4575==    by 0x4009D5: cpytoheap(char const*) (pratice.cpp:6)
    ==4575==    by 0x400A4E: main (pratice.cpp:19)
    ==4575== 
    ==4575== Invalid write of size 1
    ==4575==    at 0x400A00: cpytoheap(char const*) (pratice.cpp:9)
    ==4575==    by 0x400A4E: main (pratice.cpp:19)
    ==4575==  Address 0x5a08041 is 0 bytes after a block of size 1 alloc'd
    ==4575==    at 0x4C2B1C7: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==4575==    by 0x4009D5: cpytoheap(char const*) (pratice.cpp:6)
    ==4575==    by 0x400A4E: main (pratice.cpp:19)
    ==4575== 
    ==4575== Invalid read of size 1
    ==4575==    at 0x4C2BFB4: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==4575==    by 0x4EC7288: std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.18)
    ==4575==    by 0x400A63: main (pratice.cpp:20)
    ==4575==  Address 0x5a08041 is 0 bytes after a block of size 1 alloc'd
    ==4575==    at 0x4C2B1C7: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==4575==    by 0x4009D5: cpytoheap(char const*) (pratice.cpp:6)
    ==4575==    by 0x400A4E: main (pratice.cpp:19)
    ==4575== 
    ==4575== Invalid read of size 1
    ==4575==    at 0x53C8132: _IO_default_xsputn (genops.c:485)
    ==4575==    by 0x53C6069: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1393)
    ==4575==    by 0x53BBCDC: fwrite (iofwrite.c:45)
    ==4575==    by 0x4EC6FD4: std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.18)
    ==4575==    by 0x4EC7296: std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.18)
    ==4575==    by 0x400A63: main (pratice.cpp:20)
    ==4575==  Address 0x5a08041 is 0 bytes after a block of size 1 alloc'd
    ==4575==    at 0x4C2B1C7: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==4575==    by 0x4009D5: cpytoheap(char const*) (pratice.cpp:6)
    ==4575==    by 0x400A4E: main (pratice.cpp:19)
    ==4575== 
    ==4575== Mismatched free() / delete / delete []
    ==4575==    at 0x4C2A09C: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==4575==    by 0x400A76: main (pratice.cpp:21)
    ==4575==  Address 0x5a08040 is 0 bytes inside a block of size 1 alloc'd
    ==4575==    at 0x4C2B1C7: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==4575==    by 0x4009D5: cpytoheap(char const*) (pratice.cpp:6)
    ==4575==    by 0x400A4E: main (pratice.cpp:19)
    ==4575== 
    asdf
    q