c++ new/delete and char *

醉酒当歌 提交于 2020-11-30 04:58:29

问题


Can anyone help me, why I'm getting an error message while trying to free the allocated memory: Heap corruption detected. CTR detected the application wrote the memory after end of heap buffer.

char *ff (char *s){
    char *s1 = new char [strlen(s)];
    strcpy(s1, s);
    return s1;
}

int _tmain(int argc, _TCHAR* argv[])
{
    char *s = new char [5];

    strcpy(s, "hello");
    char *s2 = ff(s);

    delete []s;     // This works normal
    delete []s2;    // But I get an error on that line
    return 0;
}

回答1:


char *s = new char [5];
strcpy(s, "hello");

Causes Undefined behavior(UB).
You are writing beyond the bounds of allocated memery. You allocated enough memory for 5 characters but your string has 6 characters including the \0.

Once your program has caused this UB, all bets are off and any behavior is possible.

You need:

char *s = new char [strlen("hello") + 1];

In fact the ideal solution is to use std::string and not char *. These are precisley the mistakes which std::string avoids. And there is no real need of using char * instead of std::string in your example.
With std::string:

  • You don't need to new anything
  • You don't need to delete anything &
  • You can do everything with std::string, that you do with char *.



回答2:


new char [strlen(s)]; does not count the closing \0 character, so your buffer is too short by one character.




回答3:


strcpy includes the null terminator; strlen does not. Write:

char *s1 = new char [strlen(s) + 1];



回答4:


From man strcpy(3):

The strcpy() function copies the string pointed to by src, including the terminating null byte ('\0'), to the buffer pointed to by dest.

So you need to reserve 6 bytes 5 for the string and 1 for the NULL byte

char *s = new char [6];
strcpy(s, "hello");



回答5:


All answers so far have addressed either the first or the second allocation. To sum up, there are two changes you must make:

char *s1 = new char [strlen(s) + 1];
...
char *s = new char [5 + 1];

In both cases, you must allocate enough space for the string plus one byte for the terminating '\0'.

As others already pointed out, with c++ it's easier and safer to use std::string. No fuss with allocation and release of memory or paying attention to '\0' bytes:

std::string ff (const std::string &s){
    std::string s1(s);
    // do something else with s1
    return s1;
}

int main(int argc, char* argv[])
{
    std::string s("hello");
    std::string s2 = ff(s);
    return 0;
}

and if it's just copying the string:

std::string s("hello");
std::string s2(s);



回答6:


You need to specify char *s1 = new char [strlen(s) + 1]; to make room for the '\0' which terminates the string.




回答7:


You've corrupted s2 pointer by

strcpy(s, "hello");

Because s has size 5, while you've missed that strcpy includes string terminator.




回答8:


Your initial string s is only five characters long so can't be null terminated. "hello" will be copied by strcpy including the null-terminator but you'll have overrun the buffer. The strlen needs it to be null terminated so if the null's not there, you'll have problems. Try changing this line:

char *s = new char [6];

Better still, prefer std::string to C style string functions - they're just as efficient and a lot safer and easier to use. Also, try to avoid new and delete unless you really have to use them. The problems you're getting are very common and can easily be avoided.



来源:https://stackoverflow.com/questions/13247126/c-new-delete-and-char

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!