Heap corruption while freeing memory
Asked Answered
H

4

5

I have a class as follows

 struct CliHandler {
     CliHandler(int argc, char** argv);
     ~CliHandler();

     int doWork();

     int argc_; 
     char** argv_;  
     private:
     CliHandler(const CliHandler&){}
     CliHandler& operator=(const CliHandler&){} 
 };

//Constructor

 CliHandler::CliHandler(int argc,
 char** argv) {
     //set command line parameters
     argc_ = argc; 

     argv_ = (char**) malloc(argc_ * sizeof(char*));

     for(int i=0; i<argc_; ++i)
     {
         std::cout<<sizeof(argv[i]); 
         argv_[i] = (char*) malloc(strlen(argv[i]) *
 sizeof(char));
         StrCpy(argv_[i], argv[i]);
     } }

// destructor

 CliHandler::~CliHandler() {
     for(int i=0; i<argc_; ++i)
         free(argv_[i]); 
     free(argv_);  }

While I debug, I get an error " Heap corruption detected. CRT detected that application wrote to memory after end of heap buffer. " My question id "Where exactly am i making a mistake ? How do I fix it". I am using visual stdio 2008.

Edit:I did something like this to add 1

argv_[i] = (char*) malloc(strlen(argv[i] + 1) * sizeof(char));

Which is terrible as it increments the pointer argv[i] by one. My co-worker pointed out that subtle issue. It should be

argv_[i] = (char*) malloc( (strlen(argv[i]) + 1) * sizeof(char));

Hylton answered 9/5, 2011 at 19:38 Comment(5)
One thing that I see is that you don't allocate space for the null-terminator. Should be strlen(argv[i]) + 1.Sinclair
Why, if you are using C++, are you using malloc? And why are you not using std:;vector and std::string?Sumerian
Another potential problem I see is that you don't follow the Rule of Three. If any copying happens, you're in trouble.Elaterite
@unapersson - i'm integrating some function with legacy code.Hylton
So what? The things you allocate to are private, so they can't be used directly by the legacy code, so you could (and should) implement them using vectors and strings. Otherwise, you are simply writing MORE legacy code.Sumerian
A
8

Change the code to:

 argv_[i] = (char*) malloc(strlen(argv[i]) + 1) ; 
 strcpy(argv_[i], argv[i]); 

It's because your StrCpy likely trashes your memory. You have to account for the terminating nul byte as well, provided your StrCpy works like the standard strcpy (which it has to in order to be useful, better just use the standard strcpy() unless you have a good reason not to).

sizeof(char) is by definition 1, so that can be omitted too.

Agave answered 9/5, 2011 at 19:43 Comment(0)
S
1

You need to allocate one character more than the strlen of a C-string if you want to copy it. This is because strlen does not count the termination null-character.

Sparke answered 9/5, 2011 at 19:44 Comment(0)
R
1

Please use strdup() - it allocates the right amount of memory and copies characters for you.

Rawdon answered 9/5, 2011 at 19:50 Comment(7)
@Arkadiy Non-standard, impossible to tell how to de-allocate, std::string is an infinitely better way of doing things, .....Sumerian
it's part of Posix standard, and you deallocate with free(). Agreed that std::string is the right way to do it.Rawdon
The guy is explicitly using C style strings here. If that's what he wants, strdup() is fine. It's in the C standard library.Marlow
@Joshua: strdup() is not part the C standard library. It is part of POSIX.1-2001.Helman
@unapersson: strdup isn't non-standard. It's just not part of the C standard. Instead it is part of the POSIX standard which specifically says you need to to free to deallocate it.Helman
@Evan If this question was tagged POSIX, that might be a good point. Unfortunately, it isn't.Sumerian
@unapersson: My point is that the claim "impossible to tell how to de-allocate" isn't true. The POSIX standard is very specific about it. I agree it isn't standard C, and therefore is less portable. But the reality is that POSIX is a fairly widely accepted standard. If you happen to be targeting a POSIX platform, there is nothing wrong with using it.Helman
S
0

If StrCpy is anything like strcpy, it will write one byte more than strlen() returns, to zero terminate the string.

Scandalize answered 9/5, 2011 at 19:42 Comment(1)
Summarizing, he needs to add space for the extra byte on the 2nd malloc()Platitudinous

© 2022 - 2024 — McMap. All rights reserved.