0

I have a piece of code:

#include<iostream>

using namespace std;

int main()
{
    char * str = new char;

    cin >> str;
    cout << str;

    delete str;
}

vs.

#include<iostream>

using namespace std;

int main()
{
    char * str = new char[30];  

    cin >> str;
    cout << str;

    delete []str;
}

When I give input to either program using STDIN, which program ensures that there are no memory leaks?

This doubt arose as our professor told us that a char * is basically equivalent to an array of chars only. So if I allocate heap memory as in the first case and let str 'hold' an array of chars, if I then delete str, does it delete the array completely? I know that the second case manages to do so.

I have already been through ->

delete vs delete[] operators in C++

delete vs delete[]

And thus I know that delete[] deletes memory allocated by new[] and delete does the same for new. But what if new itself allocates contiguous memory locations??

Community
  • 1
  • 1
transistor
  • 127
  • 3
  • 3
    The both snippets of code are wrong.:) Try to compile to code you are going to use in your post. – Vlad from Moscow Mar 27 '15 at 14:16
  • 1
    You started off well but then when you got to the premise of your question _"Now if I supply a string as an input to both the codes"_ you failed to actually show us what you're doing... – Lightness Races in Orbit Mar 27 '15 at 14:18
  • 5
    _"our professor told us that a char * is basically equivalent to an array of chars only"_ Your professor is mistaken. – Lightness Races in Orbit Mar 27 '15 at 14:19
  • I just did! It does compile on g++ on mac os x 10.9.5 – transistor Mar 27 '15 at 14:19
  • @Lightness Races in Orbit: Sorry I didn't get you. Can you please elaborate as to what info I need to provide? – transistor Mar 27 '15 at 14:20
  • @Sattwik: The second example should error with: `foo.cc:6:27: error: expected expression` – Bill Lynch Mar 27 '15 at 14:20
  • @Sattwik: The first example only allocates enough memory for the empty string. You need to either use `std::string` or allocate enough memory for the string you want to store in it. – Bill Lynch Mar 27 '15 at 14:21
  • @Bill Lynch @ Vlad : fixed it... sorry :P – transistor Mar 27 '15 at 14:22
  • @Bill Lynch :In the first example, even if I use only new char, I am still able to provide a string as an input through the terminal. And I'm not able to understand what you're saying completely. – transistor Mar 27 '15 at 14:25
  • @Sattwik: Is it not obvious? You said "I am doing X. What happens when I do X?" but failed to tell us what "X" is. – Lightness Races in Orbit Mar 27 '15 at 14:26
  • @Bill Lynch : Kindly explain what you mean to say as an answer, your input would be invaluable. I'm not an expert at C++. – transistor Mar 27 '15 at 14:26
  • @LightnessRacesinOrbit : Okay. What I mean is that I give a string say "lol octocat" as standard input. – transistor Mar 27 '15 at 14:28
  • @Sattwik: Aha! Your use of "now" confused me, as if you were introducing some code change without telling us what it was. – Lightness Races in Orbit Mar 27 '15 at 14:30
  • If you allocate a dynamic array of chars to receive user input, 99% of the time you should use `std::string` to avoid memory leaks, bugs, security flaws (what if the input string is too big?) etc. If your prof tells you otherwise, he isn't a good one. – Neil Kirk Mar 27 '15 at 14:31

3 Answers3

2

Your both first code example is wrong.

char * str = new char;  
cin >> str;

You've only allocated memory for a single character. If you read anything other than an empty string, you'll write into unallocated memory and will have undefined behaviour.

if I then delete str, does it delete the array completely?

It will only delete the one character that you allocated. The rest of the string that you wrote in unallocated memory won't be directly affected by the delete. It's not a memory leak, it's a memory corruption.

vs.

char * str = new char[];

This is not legal c++. Array size must be specified.

EDIT: After your fix, the second code is correct as long as you read a string of 29 characters or shorter. If you read a longer string, you'll get undefined behaviour again.

But what if new itself allocates contiguous memory locations?

It doesn't. new (as opposed to new[]) allocates and constructs exactly one object. And delete destroys and deallocates exactly one object.

TLDR Neither program has memory leaks but the first one has undefined behaviour due to memory corruption.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • And what is probably the worst kind of undefined behavior there is: The one where everything seems to run as it should. Just don't use `char*` if you can avoid it. Don't use `new` and `delete` if you can avoid them. (Hard to do in C++03, but very often rather easy in C++11.) – Christopher Creutzig Mar 27 '15 at 14:32
  • Wise words, @ChristopherCreutzig – eerorika Mar 27 '15 at 14:45
2

I believe that you are misunderstanding what the difference is between a memory leak and a buffer overflow.

What is a buffer overflow?

A buffer overflow occurs when we have some piece of memory that we are going to store some data in. And when we store that data, we put too much data there. For example:

int x[4];
x[0] = 7;
x[1] = 8;
x[2] = 9;
x[3] = 10;
x[4] = 11; // <-- Buffer Overflow!

Your code exhibits a potential buffer overflow because cin doesn't know how much memory you've allocated. And there's no real method to tell it that when using char * arguments. So in your first example, if you were to write any string longer than the empty string, you would cause a buffer overflow. Likewise, if you were to write more than 30 characters (including the null character) to the second example, you would also cause a buffer overflow.

What is a memory leak?

A memory leak is traditionally represented this way:

char *x = new char[30];
x[0] = 'a';
x[1] = '\0';
x = new char[10]; // <-- Memory Leak!

At this point in the code, you have no ability to call delete[] on the first allocation. You have no variable that points to that pointer. That is a memory leak.

What does delete[] do?

Let's consider that there is some bucket somewhere that can give us chunks of memory. We can grab chunks of memory from that bucket via new and new[]. When we use delete and delete[], we return those chunks of memory back to the bucket.

The agreement that we make with new and delete is that once we call delete on a piece of memory, we don't continue to use it. We don't do this, because the system may reuse that piece of memory, or it may have removed all ability to access that pointer all together.

How could this possibly work?

You have this piece of code:

char *x = new char;
cin >> x;

I'd like to tell you that it's basically the same as this piece of code:

char y;
cin >> &y;

In both cases, you've allocated space for only one char. So when we call delete on x, we're only deleteing one char. The part of the code there that will likely break is that cin will think that there is enough memory allocated for whatever string it is going to try and write to that pointer.

The fact is, there probably isn't enough space. There's only space for one char. And even the string "a", takes up 2 chars.

Bill Lynch
  • 80,138
  • 16
  • 128
  • 173
  • Either this is _really_ good psychic work, or you answered some other question instead of this one. And I honestly don't know which! Good luck – Lightness Races in Orbit Mar 27 '15 at 14:28
  • @LightnessRacesinOrbit: I'm running off of this statement in the question: _"Now if I supply a string as an input to both the codes, which one ensures that there are no memory leaks?"_ – Bill Lynch Mar 27 '15 at 14:28
  • How did you figure out what "supply a string as an input" meant? I still haven't managed it :( Supply _how_? As input to _what_? (And don't say "the codes"!) – Lightness Races in Orbit Mar 27 '15 at 14:29
  • @LightnessRacesinOrbit: Well, the code takes user input via `cin`.. And he attempts to store it as a c-string.. That doesn't seem confusing to me at all.. – Bill Lynch Mar 27 '15 at 14:30
  • Okay, input to STDIN. He could have been talking about initialising the `char` arrays or bloomin' anything. The fact that he implied he _wasn't_ supplying a string in the two given examples (with the use of the word "Now" seemingly introducing a code change after them) set me in the wrong direction. He's clarified it now. Never mind :) – Lightness Races in Orbit Mar 27 '15 at 14:30
  • Right, I think he's understood memory leaks, and isn't asking about buffer overflows (though those are a real problem with this code) — I think he's misunderstood what `std::cin` does. He doesn't know whether extracting a string into `char*` replaces the pointer (which _would_ result in a memory leak) or populates the pointee (which it does, hence buffer overflow), and he's misusing `new` to guess at a solution to the confusion. – Lightness Races in Orbit Mar 27 '15 at 14:34
0

You can't do such things. char *ptr = new char; means that you have allocated sizeof(char) bytes. If you will execute cin >> ptr, and pass there more than 1 character, you will get segfault as the memory isn`t allocated.

To allocate an array of chars you need to do it in next way: char *ptr = new char[ size ]; It will allocate size * sizeof(char) bytes. And then you can use cin >> ptr to fill it with data.

durkmurder
  • 321
  • 1
  • 4